diff options
Diffstat (limited to 'net')
80 files changed, 2460 insertions, 2323 deletions
diff --git a/net/802/tr.c b/net/802/tr.c index 4133c2207..316cc6a22 100644 --- a/net/802/tr.c +++ b/net/802/tr.c @@ -266,7 +266,7 @@ static void tr_source_route(struct sk_buff *skb,struct trh_hdr *trh,struct net_d if(entry) { #if TR_SR_DEBUG -printk("source routing for %02X %02X %02X %02X %02X %02X\n",trh->daddr[0], +printk("source routing for %02X:%02X:%02X:%02X:%02X:%02X\n",trh->daddr[0], trh->daddr[1],trh->daddr[2],trh->daddr[3],trh->daddr[4],trh->daddr[5]); #endif if(!entry->local_ring && (ntohs(entry->rcf) & TR_RCF_LEN_MASK) >> 8) diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 9a1b18270..e2012cbb3 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -292,7 +292,7 @@ static int atalk_get_info(char *buffer, char **start, off_t offset, int length) if (pos > offset + length) /* We have dumped enough */ break; } - spin_lock_bh(&atalk_sockets_lock); + spin_unlock_bh(&atalk_sockets_lock); /* The data in question runs from begin to begin+len */ *start = buffer + (offset - begin); /* Start of wanted data */ @@ -2055,24 +2055,23 @@ static struct net_proto_family atalk_family_ops= static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops)= { - PF_APPLETALK, - - atalk_release, - atalk_bind, - atalk_connect, - sock_no_socketpair, - sock_no_accept, - atalk_getname, - datagram_poll, - atalk_ioctl, - sock_no_listen, - sock_no_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - atalk_sendmsg, - atalk_recvmsg, - sock_no_mmap + family: PF_APPLETALK, + + release: atalk_release, + bind: atalk_bind, + connect: atalk_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: atalk_getname, + poll: datagram_poll, + ioctl: atalk_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: atalk_sendmsg, + recvmsg: atalk_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/atm/clip.c b/net/atm/clip.c index 37610d6d6..f1bd99b94 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c @@ -172,7 +172,7 @@ static int clip_arp_rcv(struct sk_buff *skb) DPRINTK("clip_arp_rcv\n"); vcc = ATM_SKB(skb)->vcc; if (!vcc || !atm_charge(vcc,skb->truesize)) { - kfree_skb(skb); + dev_kfree_skb_any(skb); return 0; } DPRINTK("pushing to %p\n",vcc); @@ -197,9 +197,8 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) atm_return(vcc,skb->truesize); skb->dev = clip_vcc->entry ? clip_vcc->entry->neigh->dev : clip_devs; /* clip_vcc->entry == NULL if we don't have an IP address yet */ - skb->rx_dev = NULL; if (!skb->dev) { - kfree_skb(skb); + dev_kfree_skb_any(skb); return; } ATM_SKB(skb)->vcc = vcc; @@ -232,18 +231,20 @@ void clip_push(struct atm_vcc *vcc,struct sk_buff *skb) static void clip_pop(struct atm_vcc *vcc,struct sk_buff *skb) { struct clip_vcc *clip_vcc = CLIP_VCC(vcc); + struct net_device *dev = skb->dev; int old; + unsigned long flags; DPRINTK("clip_pop(vcc %p)\n",vcc); clip_vcc->old_pop(vcc,skb); /* skb->dev == NULL in outbound ARP packets */ - if (!skb->dev) return; - spin_lock(&PRIV(skb->dev)->xoff_lock); + if (!dev) return; + spin_lock_irqsave(&PRIV(dev)->xoff_lock,flags); if (atm_may_send(vcc,0)) { old = xchg(&clip_vcc->xoff,0); - if (old) netif_wake_queue(skb->dev); + if (old) netif_wake_queue(dev); } - spin_unlock(&PRIV(skb->dev)->xoff_lock); + spin_unlock_irqrestore(&PRIV(dev)->xoff_lock,flags); } @@ -377,6 +378,7 @@ static int clip_start_xmit(struct sk_buff *skb,struct net_device *dev) struct atmarp_entry *entry; struct atm_vcc *vcc; int old; + unsigned long flags; DPRINTK("clip_start_xmit (skb %p)\n",skb); if (!skb->dst) { @@ -439,7 +441,7 @@ return 0; return 0; } if (old) return 0; - spin_lock(&clip_priv->xoff_lock); + spin_lock_irqsave(&clip_priv->xoff_lock,flags); netif_stop_queue(dev); /* XOFF -> throttle immediately */ barrier(); if (!entry->vccs->xoff) @@ -448,7 +450,7 @@ return 0; good enough, because nothing should really be asleep because of the brief netif_stop_queue. If this isn't true or if it changes, use netif_wake_queue instead. */ - spin_unlock(&clip_priv->xoff_lock); + spin_unlock_irqrestore(&clip_priv->xoff_lock,flags); return 0; } diff --git a/net/atm/common.c b/net/atm/common.c index 9625061eb..867085ed8 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -114,7 +114,6 @@ int atm_create(struct socket *sock,int protocol,int family) vcc->atm_options = vcc->aal_options = 0; vcc->timestamp.tv_sec = vcc->timestamp.tv_usec = 0; init_waitqueue_head(&vcc->sleep); - init_waitqueue_head(&vcc->wsleep); skb_queue_head_init(&vcc->recvq); skb_queue_head_init(&vcc->listenq); sock->sk = sk; @@ -412,7 +411,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len, if (!size) return 0; /* verify_area is done by net/socket.c */ eff = (size+3) & ~3; /* align to word boundary */ - add_wait_queue(&vcc->wsleep,&wait); + add_wait_queue(&vcc->sleep,&wait); set_current_state(TASK_INTERRUPTIBLE); error = 0; while (!(skb = vcc->alloc_tx(vcc,eff))) { @@ -437,7 +436,7 @@ int atm_sendmsg(struct socket *sock,struct msghdr *m,int total_len, } } set_current_state(TASK_RUNNING); - remove_wait_queue(&vcc->wsleep,&wait); + remove_wait_queue(&vcc->sleep,&wait); if (error) return error; skb->dev = NULL; /* for paths shared with net_device interfaces */ ATM_SKB(skb)->iovcnt = 0; @@ -459,7 +458,6 @@ unsigned int atm_poll(struct file *file,struct socket *sock,poll_table *wait) vcc = ATM_SD(sock); poll_wait(file,&vcc->sleep,wait); - poll_wait(file,&vcc->wsleep,wait); mask = 0; if (skb_peek(&vcc->recvq) || skb_peek(&vcc->listenq)) mask |= POLLIN | POLLRDNORM; diff --git a/net/atm/common.h b/net/atm/common.h index cbd2e4edf..faf1866ac 100644 --- a/net/atm/common.h +++ b/net/atm/common.h @@ -1,6 +1,6 @@ /* net/atm/common.h - ATM sockets (common part for PVC and SVC) */ -/* Written 1995-1998 by Werner Almesberger, EPFL LRC/ICA */ +/* Written 1995-2000 by Werner Almesberger, EPFL LRC/ICA */ #ifndef NET_ATM_COMMON_H @@ -27,9 +27,6 @@ int atm_getsockopt(struct socket *sock,int level,int optname,char *optval, int atm_connect_vcc(struct atm_vcc *vcc,int itf,short vpi,int vci); void atm_release_vcc_sk(struct sock *sk,int free_sk); int atm_change_qos(struct atm_vcc *vcc,struct atm_qos *qos); -/* -- now in atmdev.h: -void atm_async_release_vcc(struct atm_vcc *vcc,int reply); -*/ void atm_shutdown_dev(struct atm_dev *dev); int atm_proc_init(void); diff --git a/net/atm/lane_mpoa_init.c b/net/atm/lane_mpoa_init.c index 469685703..448826dd2 100644 --- a/net/atm/lane_mpoa_init.c +++ b/net/atm/lane_mpoa_init.c @@ -38,12 +38,10 @@ void atm_mpoa_init(void) #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) -rwlock_t lane_bridge_hook_lock = RW_LOCK_UNLOCKED; struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, unsigned char *addr) = NULL; void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent) = NULL; #if defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) -EXPORT_SYMBOL(lane_bridge_hook_lock); EXPORT_SYMBOL(br_fdb_get_hook); EXPORT_SYMBOL(br_fdb_put_hook); #endif /* defined(CONFIG_ATM_LANE_MODULE) || defined(CONFIG_BRIDGE_MODULE) */ diff --git a/net/atm/lec.c b/net/atm/lec.c index 701ece763..96f2877cf 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c @@ -34,7 +34,7 @@ #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #include <linux/if_bridge.h> #include "../bridge/br_private.h" -unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; +static unsigned char bridge_ula[] = {0x01, 0x80, 0xc2, 0x00, 0x00}; #endif /* Modular too */ @@ -472,11 +472,8 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) mesg->content.proxy.mac_addr[2], mesg->content.proxy.mac_addr[3], mesg->content.proxy.mac_addr[4], mesg->content.proxy.mac_addr[5]); - read_lock(&lane_bridge_hook_lock); - if (br_fdb_get_hook == NULL || dev->br_port == NULL) { - read_unlock(&lane_bridge_hook_lock); + if (br_fdb_get_hook == NULL || dev->br_port == NULL) break; - } f = br_fdb_get_hook(dev->br_port->br, mesg->content.proxy.mac_addr); if (f != NULL && @@ -489,7 +486,6 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) skb2 = alloc_skb(sizeof(struct atmlec_msg), GFP_ATOMIC); if (skb2 == NULL) { br_fdb_put_hook(f); - read_unlock(&lane_bridge_hook_lock); break; } skb2->len = sizeof(struct atmlec_msg); @@ -499,7 +495,6 @@ lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) wake_up(&priv->lecd->sleep); } if (f != NULL) br_fdb_put_hook(f); - read_unlock(&lane_bridge_hook_lock); #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ } break; @@ -696,7 +691,6 @@ lec_push(struct atm_vcc *vcc, struct sk_buff *skb) lec_arp_check_empties(priv, vcc, skb); } skb->dev = dev; - skb->rx_dev = NULL; skb->data += 2; /* skip lec_id */ #ifdef CONFIG_TR if (priv->is_trdev) skb->protocol = tr_type_trans(skb, dev); @@ -1079,8 +1073,8 @@ lec_arp_clear_vccs(struct lec_arp_table *entry) if (entry->recv_vcc) { entry->recv_vcc->push = entry->old_recv_push; #if 0 - set_bit(ATM_VF_RELEASED,&entry->vcc->flags); - clear_bit(ATM_VF_READY,&entry->vcc->flags); + set_bit(ATM_VF_RELEASED,&entry->recv_vcc->flags); + clear_bit(ATM_VF_READY,&entry->recv_vcc->flags); entry->recv_vcc->push(entry->recv_vcc, NULL); #endif atm_async_release_vcc(entry->recv_vcc, -EPIPE); diff --git a/net/atm/lec.h b/net/atm/lec.h index df08e6803..f40a37fa3 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h @@ -16,7 +16,6 @@ #if defined (CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) #include <linux/if_bridge.h> -extern rwlock_t lane_bridge_hook_lock; struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, unsigned char *addr); void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); diff --git a/net/atm/mpc.c b/net/atm/mpc.c index deeb737f5..1b3e13ad6 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c @@ -62,7 +62,7 @@ static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *m static void set_mps_mac_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc); static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac, - uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type); + uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type); static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry); static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc); @@ -76,25 +76,25 @@ static void mpc_timer_refresh(void); static void mpc_cache_check( unsigned long checking_time ); static struct llc_snap_hdr llc_snap_mpoa_ctrl = { - 0xaa, 0xaa, 0x03, - {0x00, 0x00, 0x5e}, - {0x00, 0x03} /* For MPOA control PDUs */ + 0xaa, 0xaa, 0x03, + {0x00, 0x00, 0x5e}, + {0x00, 0x03} /* For MPOA control PDUs */ }; static struct llc_snap_hdr llc_snap_mpoa_data = { - 0xaa, 0xaa, 0x03, - {0x00, 0x00, 0x00}, - {0x08, 0x00} /* This is for IP PDUs only */ + 0xaa, 0xaa, 0x03, + {0x00, 0x00, 0x00}, + {0x08, 0x00} /* This is for IP PDUs only */ }; static struct llc_snap_hdr llc_snap_mpoa_data_tagged = { - 0xaa, 0xaa, 0x03, - {0x00, 0x00, 0x00}, - {0x88, 0x4c} /* This is for tagged data PDUs */ + 0xaa, 0xaa, 0x03, + {0x00, 0x00, 0x00}, + {0x88, 0x4c} /* This is for tagged data PDUs */ }; static struct notifier_block mpoa_notifier = { - mpoa_event_listener, - NULL, - 0 + mpoa_event_listener, + NULL, + 0 }; #ifdef CONFIG_PROC_FS @@ -109,44 +109,44 @@ static struct timer_list mpc_timer; static struct mpoa_client *find_mpc_by_itfnum(int itf) { - struct mpoa_client *mpc; - - mpc = mpcs; /* our global linked list */ - while (mpc != NULL) { - if (mpc->dev_num == itf) - return mpc; - mpc = mpc->next; - } - - return NULL; /* not found */ + struct mpoa_client *mpc; + + mpc = mpcs; /* our global linked list */ + while (mpc != NULL) { + if (mpc->dev_num == itf) + return mpc; + mpc = mpc->next; + } + + return NULL; /* not found */ } static struct mpoa_client *find_mpc_by_vcc(struct atm_vcc *vcc) { - struct mpoa_client *mpc; - - mpc = mpcs; /* our global linked list */ - while (mpc != NULL) { - if (mpc->mpoad_vcc == vcc) - return mpc; - mpc = mpc->next; - } - - return NULL; /* not found */ + struct mpoa_client *mpc; + + mpc = mpcs; /* our global linked list */ + while (mpc != NULL) { + if (mpc->mpoad_vcc == vcc) + return mpc; + mpc = mpc->next; + } + + return NULL; /* not found */ } static struct mpoa_client *find_mpc_by_lec(struct net_device *dev) { - struct mpoa_client *mpc; - - mpc = mpcs; /* our global linked list */ - while (mpc != NULL) { - if (mpc->dev == dev) - return mpc; - mpc = mpc->next; - } - - return NULL; /* not found */ + struct mpoa_client *mpc; + + mpc = mpcs; /* our global linked list */ + while (mpc != NULL) { + if (mpc->dev == dev) + return mpc; + mpc = mpc->next; + } + + return NULL; /* not found */ } /* @@ -158,42 +158,42 @@ static struct mpoa_client *find_mpc_by_lec(struct net_device *dev) */ struct atm_mpoa_qos *atm_mpoa_add_qos(uint32_t dst_ip, struct atm_qos *qos) { - struct atm_mpoa_qos *entry; + struct atm_mpoa_qos *entry; - entry = atm_mpoa_search_qos(dst_ip); - if (entry != NULL) { - entry->qos = *qos; - return entry; - } + entry = atm_mpoa_search_qos(dst_ip); + if (entry != NULL) { + entry->qos = *qos; + return entry; + } - entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL); - if (entry == NULL) { - printk("mpoa: atm_mpoa_add_qos: out of memory\n"); - return entry; - } + entry = kmalloc(sizeof(struct atm_qos), GFP_KERNEL); + if (entry == NULL) { + printk("mpoa: atm_mpoa_add_qos: out of memory\n"); + return entry; + } - entry->ipaddr = dst_ip; - entry->qos = *qos; + entry->ipaddr = dst_ip; + entry->qos = *qos; - entry->next = qos_head; - qos_head = entry; + entry->next = qos_head; + qos_head = entry; - return entry; + return entry; } struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip) { - struct atm_mpoa_qos *qos; + struct atm_mpoa_qos *qos; - qos = qos_head; - while( qos != NULL ){ - if(qos->ipaddr == dst_ip) { - break; + qos = qos_head; + while( qos != NULL ){ + if(qos->ipaddr == dst_ip) { + break; } - qos = qos->next; - } + qos = qos->next; + } - return qos; + return qos; } /* @@ -202,26 +202,26 @@ struct atm_mpoa_qos *atm_mpoa_search_qos(uint32_t dst_ip) int atm_mpoa_delete_qos(struct atm_mpoa_qos *entry) { - struct atm_mpoa_qos *curr; - - if (entry == NULL) return 0; - if (entry == qos_head) { - qos_head = qos_head->next; - kfree(entry); - return 1; - } - - curr = qos_head; - while (curr != NULL) { - if (curr->next == entry) { - curr->next = entry->next; - kfree(entry); - return 1; - } - curr = curr->next; - } - - return 0; + struct atm_mpoa_qos *curr; + + if (entry == NULL) return 0; + if (entry == qos_head) { + qos_head = qos_head->next; + kfree(entry); + return 1; + } + + curr = qos_head; + while (curr != NULL) { + if (curr->next == entry) { + curr->next = entry->next; + kfree(entry); + return 1; + } + curr = curr->next; + } + + return 0; } void atm_mpoa_disp_qos(char *page, int *len) @@ -238,9 +238,9 @@ void atm_mpoa_disp_qos(char *page, int *len) ipaddr[sizeof(ipaddr)-1] = '\0'; while (qos != NULL) { ip = (unsigned char *)&qos->ipaddr; - sprintf(ipaddr, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); - *len += sprintf(page + *len, "%-16s\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", - ipaddr, + sprintf(ipaddr, "%u.%u.%u.%u", NIPQUAD(ip)); + *len += sprintf(page + *len, "%%u.%u.%u.%u\n %-7d %-7d %-7d %-7d %-7d\n %-7d %-7d %-7d %-7d %-7d\n", + NIPQUAD(ipaddr), qos->qos.txtp.max_pcr, qos->qos.txtp.pcr, qos->qos.txtp.min_pcr, qos->qos.txtp.max_cdv, qos->qos.txtp.max_sdu, qos->qos.rxtp.max_pcr, qos->qos.rxtp.pcr, qos->qos.rxtp.min_pcr, qos->qos.rxtp.max_cdv, qos->qos.rxtp.max_sdu); qos = qos->next; @@ -251,28 +251,26 @@ void atm_mpoa_disp_qos(char *page, int *len) static struct net_device *find_lec_by_itfnum(int itf) { - extern struct atm_lane_ops atm_lane_ops; /* in common.c */ - - if (atm_lane_ops.get_lecs == NULL) - return NULL; + extern struct atm_lane_ops atm_lane_ops; /* in common.c */ + + if (atm_lane_ops.get_lecs == NULL) + return NULL; - return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */ + return atm_lane_ops.get_lecs()[itf]; /* FIXME: something better */ } static struct mpoa_client *alloc_mpc(void) { - struct mpoa_client *mpc; - - mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL); - if (mpc == NULL) - return NULL; - memset(mpc, 0, sizeof(struct mpoa_client)); -#if 0 /* compiler seems to barf on this */ - mpc->ingress_lock = RW_LOCK_UNLOCKED; - mpc->egress_lock = RW_LOCK_UNLOCKED; -#endif - mpc->next = mpcs; - atm_mpoa_init_cache(mpc); + struct mpoa_client *mpc; + + mpc = kmalloc(sizeof (struct mpoa_client), GFP_KERNEL); + if (mpc == NULL) + return NULL; + memset(mpc, 0, sizeof(struct mpoa_client)); + mpc->ingress_lock = RW_LOCK_UNLOCKED; + mpc->egress_lock = RW_LOCK_UNLOCKED; + mpc->next = mpcs; + atm_mpoa_init_cache(mpc); mpc->parameters.mpc_p1 = MPC_P1; mpc->parameters.mpc_p2 = MPC_P2; @@ -281,9 +279,9 @@ static struct mpoa_client *alloc_mpc(void) mpc->parameters.mpc_p5 = MPC_P5; mpc->parameters.mpc_p6 = MPC_P6; - mpcs = mpc; + mpcs = mpc; - return mpc; + return mpc; } /* @@ -295,58 +293,58 @@ static struct mpoa_client *alloc_mpc(void) */ static void start_mpc(struct mpoa_client *mpc, struct net_device *dev) { - - dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); - if (dev->hard_start_xmit == NULL) { - printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n", - dev->name); - return; - } - mpc->old_hard_start_xmit = dev->hard_start_xmit; - dev->hard_start_xmit = mpc_send_packet; - - return; + + dprintk("mpoa: (%s) start_mpc:\n", mpc->dev->name); + if (dev->hard_start_xmit == NULL) { + printk("mpoa: (%s) start_mpc: dev->hard_start_xmit == NULL, not starting\n", + dev->name); + return; + } + mpc->old_hard_start_xmit = dev->hard_start_xmit; + dev->hard_start_xmit = mpc_send_packet; + + return; } static void stop_mpc(struct mpoa_client *mpc) { - - dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); - - /* Lets not nullify lec device's dev->hard_start_xmit */ - if (mpc->dev->hard_start_xmit != mpc_send_packet) { - dprintk(" mpc already stopped, not fatal\n"); - return; - } - dprintk("\n"); - mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit; - mpc->old_hard_start_xmit = NULL; + + dprintk("mpoa: (%s) stop_mpc:", mpc->dev->name); + + /* Lets not nullify lec device's dev->hard_start_xmit */ + if (mpc->dev->hard_start_xmit != mpc_send_packet) { + dprintk(" mpc already stopped, not fatal\n"); + return; + } + dprintk("\n"); + mpc->dev->hard_start_xmit = mpc->old_hard_start_xmit; + mpc->old_hard_start_xmit = NULL; /* close_shortcuts(mpc); ??? FIXME */ - - return; + + return; } static const char * __attribute__ ((unused)) mpoa_device_type_string(char type) { - switch(type) { - case NON_MPOA: - return "non-MPOA device"; - break; - case MPS: - return "MPS"; - break; - case MPC: - return "MPC"; - break; - case MPS_AND_MPC: - return "both MPS and MPC"; - break; - default: - return "unspecified (non-MPOA) device"; - break; - } - - return ""; /* not reached */ + switch(type) { + case NON_MPOA: + return "non-MPOA device"; + break; + case MPS: + return "MPS"; + break; + case MPC: + return "MPC"; + break; + case MPS_AND_MPC: + return "both MPS and MPC"; + break; + default: + return "unspecified (non-MPOA) device"; + break; + } + + return ""; /* not reached */ } /* @@ -363,77 +361,77 @@ static const char * __attribute__ ((unused)) mpoa_device_type_string(char type) * */ static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr, - uint8_t *tlvs, uint32_t sizeoftlvs) + uint8_t *tlvs, uint32_t sizeoftlvs) { - uint32_t type; - uint8_t length, mpoa_device_type, number_of_mps_macs; - uint8_t *end_of_tlvs; - struct mpoa_client *mpc; - - mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */ - dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name); - dprintk("total length of all TLVs %d\n", sizeoftlvs); + uint32_t type; + uint8_t length, mpoa_device_type, number_of_mps_macs; + uint8_t *end_of_tlvs; + struct mpoa_client *mpc; + + mpoa_device_type = number_of_mps_macs = 0; /* silence gcc */ + dprintk("mpoa: (%s) lane2_assoc_ind: received TLV(s), ", dev->name); + dprintk("total length of all TLVs %d\n", sizeoftlvs); mpc = find_mpc_by_lec(dev); /* Sampo-Fix: moved here from below */ - if (mpc == NULL) { - printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name); - return; - } - end_of_tlvs = tlvs + sizeoftlvs; - while (end_of_tlvs - tlvs >= 5) { - type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3]; - length = tlvs[4]; - tlvs += 5; - dprintk(" type 0x%x length %02x\n", type, length); - if (tlvs + length > end_of_tlvs) { - printk("TLV value extends past its buffer, aborting parse\n"); - return; - } - - if (type == 0) { - printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name); - return; + if (mpc == NULL) { + printk("mpoa: (%s) lane2_assoc_ind: no mpc\n", dev->name); + return; + } + end_of_tlvs = tlvs + sizeoftlvs; + while (end_of_tlvs - tlvs >= 5) { + type = (tlvs[0] << 24) | (tlvs[1] << 16) | (tlvs[2] << 8) | tlvs[3]; + length = tlvs[4]; + tlvs += 5; + dprintk(" type 0x%x length %02x\n", type, length); + if (tlvs + length > end_of_tlvs) { + printk("TLV value extends past its buffer, aborting parse\n"); + return; + } + + if (type == 0) { + printk("mpoa: (%s) lane2_assoc_ind: TLV type was 0, returning\n", dev->name); + return; } - if (type != TLV_MPOA_DEVICE_TYPE) { - tlvs += length; - continue; /* skip other TLVs */ - } - mpoa_device_type = *tlvs++; - number_of_mps_macs = *tlvs++; - dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type)); - if (mpoa_device_type == MPS_AND_MPC && - length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */ - printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n", - dev->name); - continue; - } - if ((mpoa_device_type == MPS || mpoa_device_type == MPC) - && length < 22 + number_of_mps_macs*ETH_ALEN) { - printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n", - dev->name); - continue; - } - if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) { - dprintk("ignoring non-MPS device\n"); - if (mpoa_device_type == MPC) tlvs += 20; - continue; /* we are only interested in MPSs */ - } - if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) { - printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name); - continue; /* someone should read the spec */ - } - dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs); - - /* ok, now we can go and tell our daemon the control address of MPS */ - send_set_mps_ctrl_addr(tlvs, mpc); - - tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type); - if (tlvs == NULL) return; - } - if (end_of_tlvs - tlvs != 0) - printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n", - dev->name, end_of_tlvs - tlvs); - return; + if (type != TLV_MPOA_DEVICE_TYPE) { + tlvs += length; + continue; /* skip other TLVs */ + } + mpoa_device_type = *tlvs++; + number_of_mps_macs = *tlvs++; + dprintk("mpoa: (%s) MPOA device type '%s', ", dev->name, mpoa_device_type_string(mpoa_device_type)); + if (mpoa_device_type == MPS_AND_MPC && + length < (42 + number_of_mps_macs*ETH_ALEN)) { /* :) */ + printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n", + dev->name); + continue; + } + if ((mpoa_device_type == MPS || mpoa_device_type == MPC) + && length < 22 + number_of_mps_macs*ETH_ALEN) { + printk("\nmpoa: (%s) lane2_assoc_ind: short MPOA Device Type TLV\n", + dev->name); + continue; + } + if (mpoa_device_type != MPS && mpoa_device_type != MPS_AND_MPC) { + dprintk("ignoring non-MPS device\n"); + if (mpoa_device_type == MPC) tlvs += 20; + continue; /* we are only interested in MPSs */ + } + if (number_of_mps_macs == 0 && mpoa_device_type == MPS_AND_MPC) { + printk("\nmpoa: (%s) lane2_assoc_ind: MPS_AND_MPC has zero MACs\n", dev->name); + continue; /* someone should read the spec */ + } + dprintk("this MPS has %d MAC addresses\n", number_of_mps_macs); + + /* ok, now we can go and tell our daemon the control address of MPS */ + send_set_mps_ctrl_addr(tlvs, mpc); + + tlvs = copy_macs(mpc, mac_addr, tlvs, number_of_mps_macs, mpoa_device_type); + if (tlvs == NULL) return; + } + if (end_of_tlvs - tlvs != 0) + printk("mpoa: (%s) lane2_assoc_ind: ignoring %d bytes of trailing TLV carbage\n", + dev->name, end_of_tlvs - tlvs); + return; } /* @@ -442,91 +440,94 @@ static void lane2_assoc_ind(struct net_device *dev, uint8_t *mac_addr, * For a freshly allocated MPOA client mpc->mps_macs == 0. */ static uint8_t *copy_macs(struct mpoa_client *mpc, uint8_t *router_mac, - uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type) + uint8_t *tlvs, uint8_t mps_macs, uint8_t device_type) { - int num_macs; - num_macs = (mps_macs > 1) ? mps_macs : 1; - - if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */ - if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs); - mpc->number_of_mps_macs = 0; - mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL); - if (mpc->mps_macs == NULL) { - printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name); - return NULL; - } - } - memcpy(mpc->mps_macs, router_mac, ETH_ALEN); - tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20; - if (mps_macs > 0) - memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN); - tlvs += mps_macs*ETH_ALEN; - mpc->number_of_mps_macs = num_macs; - - return tlvs; + int num_macs; + num_macs = (mps_macs > 1) ? mps_macs : 1; + + if (mpc->number_of_mps_macs != num_macs) { /* need to reallocate? */ + if (mpc->number_of_mps_macs != 0) kfree(mpc->mps_macs); + mpc->number_of_mps_macs = 0; + mpc->mps_macs = kmalloc(num_macs*ETH_ALEN, GFP_KERNEL); + if (mpc->mps_macs == NULL) { + printk("mpoa: (%s) copy_macs: out of mem\n", mpc->dev->name); + return NULL; + } + } + memcpy(mpc->mps_macs, router_mac, ETH_ALEN); + tlvs += 20; if (device_type == MPS_AND_MPC) tlvs += 20; + if (mps_macs > 0) + memcpy(mpc->mps_macs, tlvs, mps_macs*ETH_ALEN); + tlvs += mps_macs*ETH_ALEN; + mpc->number_of_mps_macs = num_macs; + + return tlvs; } -/* FIXME: tarvitsee työtä */ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) { - in_cache_entry *entry; - struct iphdr *iph; - char *buff; - uint32_t ipaddr = 0; - - static struct { - struct llc_snap_hdr hdr; - uint32_t tag; - } tagged_llc_snap_hdr = { - {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}}, - 0 - }; - - buff = skb->data + mpc->dev->hard_header_len; - iph = (struct iphdr *)buff; + in_cache_entry *entry; + struct iphdr *iph; + char *buff; + uint32_t ipaddr = 0; + + static struct { + struct llc_snap_hdr hdr; + uint32_t tag; + } tagged_llc_snap_hdr = { + {0xaa, 0xaa, 0x03, {0x00, 0x00, 0x00}, {0x88, 0x4c}}, + 0 + }; + + buff = skb->data + mpc->dev->hard_header_len; + iph = (struct iphdr *)buff; ipaddr = iph->daddr; - ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr); - - entry = mpc->in_ops->search(ipaddr, mpc); - if (entry == NULL) { - mpc->in_ops->new_entry(ipaddr, mpc); - return 1; - } - if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */ - ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name); - return 1; - } - - ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name); - /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */ - if (iph->ttl <= 1) { - ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl); - return 1; - } - iph->ttl--; - iph->check = 0; - iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); - - if (entry->ctrl_info.tag != 0) { - ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag); - tagged_llc_snap_hdr.tag = entry->ctrl_info.tag; - skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ - skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */ - memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr)); - } else { - skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ - skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */ - memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)); - } - - atomic_add(skb->truesize, &entry->shortcut->tx_inuse); + ddprintk("mpoa: (%s) send_via_shortcut: ipaddr 0x%x\n", mpc->dev->name, ipaddr); + + entry = mpc->in_ops->get(ipaddr, mpc); + if (entry == NULL) { + entry = mpc->in_ops->add_entry(ipaddr, mpc); + if (entry != NULL) mpc->in_ops->put(entry); + return 1; + } + if (mpc->in_ops->cache_hit(entry, mpc) != OPEN){ /* threshold not exceeded or VCC not ready */ + ddprintk("mpoa: (%s) send_via_shortcut: cache_hit: returns != OPEN\n", mpc->dev->name); + mpc->in_ops->put(entry); + return 1; + } + + ddprintk("mpoa: (%s) send_via_shortcut: using shortcut\n", mpc->dev->name); + /* MPOA spec A.1.4, MPOA client must decrement IP ttl at least by one */ + if (iph->ttl <= 1) { + ddprintk("mpoa: (%s) send_via_shortcut: IP ttl = %u, using LANE\n", mpc->dev->name, iph->ttl); + mpc->in_ops->put(entry); + return 1; + } + iph->ttl--; + iph->check = 0; + iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); + + if (entry->ctrl_info.tag != 0) { + ddprintk("mpoa: (%s) send_via_shortcut: adding tag 0x%x\n", mpc->dev->name, entry->ctrl_info.tag); + tagged_llc_snap_hdr.tag = entry->ctrl_info.tag; + skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ + skb_push(skb, sizeof(tagged_llc_snap_hdr)); /* add LLC/SNAP header */ + memcpy(skb->data, &tagged_llc_snap_hdr, sizeof(tagged_llc_snap_hdr)); + } else { + skb_pull(skb, ETH_HLEN); /* get rid of Eth header */ + skb_push(skb, sizeof(struct llc_snap_hdr)); /* add LLC/SNAP header + tag */ + memcpy(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)); + } + + atomic_add(skb->truesize, &entry->shortcut->tx_inuse); ATM_SKB(skb)->iovcnt = 0; /* just to be safe ... */ ATM_SKB(skb)->atm_options = entry->shortcut->atm_options; - entry->shortcut->send(entry->shortcut, skb); + entry->shortcut->send(entry->shortcut, skb); entry->packets_fwded++; + mpc->in_ops->put(entry); - return 0; + return 0; } /* @@ -534,75 +535,77 @@ static int send_via_shortcut(struct sk_buff *skb, struct mpoa_client *mpc) */ static int mpc_send_packet(struct sk_buff *skb, struct net_device *dev) { - int retval; - struct mpoa_client *mpc; - struct ethhdr *eth; - int i = 0; - - mpc = find_mpc_by_lec(dev); /* this should NEVER fail */ - if(mpc == NULL) { - printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name); - goto non_ip; - } - - eth = (struct ethhdr *)skb->data; - if (eth->h_proto != htons(ETH_P_IP)) - goto non_ip; /* Multi-Protocol Over ATM :-) */ - - while (i < mpc->number_of_mps_macs) { - if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0) - if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */ - return 0; /* success! */ - i++; - } + int retval; + struct mpoa_client *mpc; + struct ethhdr *eth; + int i = 0; + + mpc = find_mpc_by_lec(dev); /* this should NEVER fail */ + if(mpc == NULL) { + printk("mpoa: (%s) mpc_send_packet: no MPC found\n", dev->name); + goto non_ip; + } + + eth = (struct ethhdr *)skb->data; + if (eth->h_proto != htons(ETH_P_IP)) + goto non_ip; /* Multi-Protocol Over ATM :-) */ + + while (i < mpc->number_of_mps_macs) { + if (memcmp(eth->h_dest, (mpc->mps_macs + i*ETH_ALEN), ETH_ALEN) == 0) + if ( send_via_shortcut(skb, mpc) == 0 ) /* try shortcut */ + return 0; /* success! */ + i++; + } non_ip: - retval = mpc->old_hard_start_xmit(skb,dev); - - return retval; + retval = mpc->old_hard_start_xmit(skb,dev); + + return retval; } int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg) { - int bytes_left; - struct mpoa_client *mpc; - struct atmmpc_ioc ioc_data; - in_cache_entry *in_entry; - uint32_t ipaddr; + int bytes_left; + struct mpoa_client *mpc; + struct atmmpc_ioc ioc_data; + in_cache_entry *in_entry; + uint32_t ipaddr; unsigned char *ip; - bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc)); - if (bytes_left != 0) { - printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left); - return -EFAULT; - } - ipaddr = ioc_data.ipaddr; - if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) - return -EINVAL; - - mpc = find_mpc_by_itfnum(ioc_data.dev_num); - if (mpc == NULL) - return -EINVAL; - - if (ioc_data.type == MPC_SOCKET_INGRESS) { - in_entry = mpc->in_ops->search(ipaddr, mpc); - if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) { - printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n", - mpc->dev->name); - return -EINVAL; - } + bytes_left = copy_from_user(&ioc_data, (void *)arg, sizeof(struct atmmpc_ioc)); + if (bytes_left != 0) { + printk("mpoa: mpc_vcc_attach: Short read (missed %d bytes) from userland\n", bytes_left); + return -EFAULT; + } + ipaddr = ioc_data.ipaddr; + if (ioc_data.dev_num < 0 || ioc_data.dev_num >= MAX_LEC_ITF) + return -EINVAL; + + mpc = find_mpc_by_itfnum(ioc_data.dev_num); + if (mpc == NULL) + return -EINVAL; + + if (ioc_data.type == MPC_SOCKET_INGRESS) { + in_entry = mpc->in_ops->get(ipaddr, mpc); + if (in_entry == NULL || in_entry->entry_state < INGRESS_RESOLVED) { + printk("mpoa: (%s) mpc_vcc_attach: did not find RESOLVED entry from ingress cache\n", + mpc->dev->name); + if (in_entry != NULL) mpc->in_ops->put(in_entry); + return -EINVAL; + } ip = (unsigned char*)&in_entry->ctrl_info.in_dst_ip; - printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n", - mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); - in_entry->shortcut = vcc; - } else { - printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name); - } - - vcc->proto_data = mpc->dev; - vcc->push = mpc_push; - - return 0; + printk("mpoa: (%s) mpc_vcc_attach: attaching ingress SVC, entry = %u.%u.%u.%u\n", + mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); + in_entry->shortcut = vcc; + mpc->in_ops->put(in_entry); + } else { + printk("mpoa: (%s) mpc_vcc_attach: attaching egress SVC\n", mpc->dev->name); + } + + vcc->proto_data = mpc->dev; + vcc->push = mpc_push; + + return 0; } /* @@ -610,251 +613,250 @@ int atm_mpoa_vcc_attach(struct atm_vcc *vcc, long arg) */ static void mpc_vcc_close(struct atm_vcc *vcc, struct net_device *dev) { - struct mpoa_client *mpc; - in_cache_entry *in_entry; - eg_cache_entry *eg_entry; - - mpc = find_mpc_by_lec(dev); - if (mpc == NULL) { - printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name); - return; - } - - dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name); - in_entry = mpc->in_ops->search_by_vcc(vcc, mpc); - if (in_entry) { - unsigned char *ip __attribute__ ((unused)) = + struct mpoa_client *mpc; + in_cache_entry *in_entry; + eg_cache_entry *eg_entry; + + mpc = find_mpc_by_lec(dev); + if (mpc == NULL) { + printk("mpoa: (%s) mpc_vcc_close: close for unknown MPC\n", dev->name); + return; + } + + dprintk("mpoa: (%s) mpc_vcc_close:\n", dev->name); + in_entry = mpc->in_ops->get_by_vcc(vcc, mpc); + if (in_entry) { + unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&in_entry->ctrl_info.in_dst_ip; - dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n", - mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); - in_entry->shortcut = NULL; - } - eg_entry = mpc->eg_ops->search_by_vcc(vcc, mpc); - if (eg_entry) { - dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name); - eg_entry->shortcut = NULL; - } - - if (in_entry == NULL && eg_entry == NULL) - dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name); - - return; + dprintk("mpoa: (%s) mpc_vcc_close: ingress SVC closed ip = %u.%u.%u.%u\n", + mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); + in_entry->shortcut = NULL; + mpc->in_ops->put(in_entry); + } + eg_entry = mpc->eg_ops->get_by_vcc(vcc, mpc); + if (eg_entry) { + dprintk("mpoa: (%s) mpc_vcc_close: egress SVC closed\n", mpc->dev->name); + eg_entry->shortcut = NULL; + mpc->eg_ops->put(eg_entry); + } + + if (in_entry == NULL && eg_entry == NULL) + dprintk("mpoa: (%s) mpc_vcc_close: unused vcc closed\n", dev->name); + + return; } static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) { - struct net_device *dev = (struct net_device *)vcc->proto_data; - struct sk_buff *new_skb; - eg_cache_entry *eg; - struct mpoa_client *mpc; + struct net_device *dev = (struct net_device *)vcc->proto_data; + struct sk_buff *new_skb; + eg_cache_entry *eg; + struct mpoa_client *mpc; uint32_t tag; - char *tmp; - - ddprintk("mpoa: (%s) mpc_push:\n", dev->name); - if (skb == NULL) { - dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name); - mpc_vcc_close(vcc, dev); - return; - } - - skb->dev = dev; - if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) { - dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name); - skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */ - wake_up(&vcc->sleep); - return; - } - - /* data coming over the shortcut */ - atm_return(vcc, skb->truesize); + char *tmp; + + ddprintk("mpoa: (%s) mpc_push:\n", dev->name); + if (skb == NULL) { + dprintk("mpoa: (%s) mpc_push: null skb, closing VCC\n", dev->name); + mpc_vcc_close(vcc, dev); + return; + } + + skb->dev = dev; + if (memcmp(skb->data, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr)) == 0) { + dprintk("mpoa: (%s) mpc_push: control packet arrived\n", dev->name); + skb_queue_tail(&vcc->recvq, skb); /* Pass control packets to daemon */ + wake_up(&vcc->sleep); + return; + } + + /* data coming over the shortcut */ + atm_return(vcc, skb->truesize); mpc = find_mpc_by_lec(dev); - if (mpc == NULL) { - printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name); - return; - } + if (mpc == NULL) { + printk("mpoa: (%s) mpc_push: unknown MPC\n", dev->name); + return; + } - if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */ - ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name); + if (memcmp(skb->data, &llc_snap_mpoa_data_tagged, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA tagged data */ + ddprintk("mpoa: (%s) mpc_push: tagged data packet arrived\n", dev->name); - } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */ - printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name); - printk(" mpc_push: non-tagged data unsupported, purging\n"); - kfree_skb(skb); - return; - } else { - printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name); - kfree_skb(skb); - return; - } - - tmp = skb->data + sizeof(struct llc_snap_hdr); - tag = *(uint32_t *)tmp; - - eg = mpc->eg_ops->search_by_tag(tag, mpc); - if (eg == NULL) { - printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n", - dev->name,tag); - purge_egress_shortcut(vcc, NULL); - kfree_skb(skb); - return; - } - - /* - * See if ingress MPC is using shortcut we opened as a return channel. - * This means we have a bi-directional vcc opened by us. - */ - if (eg->shortcut == NULL) { - eg->shortcut = vcc; - printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name); - } - - skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */ - new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */ - kfree_skb(skb); - if (new_skb == NULL) return; - skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */ - memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length); - new_skb->protocol = eth_type_trans(new_skb, dev); - new_skb->nh.raw = new_skb->data; + } else if (memcmp(skb->data, &llc_snap_mpoa_data, sizeof(struct llc_snap_hdr)) == 0) { /* MPOA data */ + printk("mpoa: (%s) mpc_push: non-tagged data packet arrived\n", dev->name); + printk(" mpc_push: non-tagged data unsupported, purging\n"); + dev_kfree_skb_any(skb); + return; + } else { + printk("mpoa: (%s) mpc_push: garbage arrived, purging\n", dev->name); + dev_kfree_skb_any(skb); + return; + } + + tmp = skb->data + sizeof(struct llc_snap_hdr); + tag = *(uint32_t *)tmp; + + eg = mpc->eg_ops->get_by_tag(tag, mpc); + if (eg == NULL) { + printk("mpoa: (%s) mpc_push: Didn't find egress cache entry, tag = %u\n", + dev->name,tag); + purge_egress_shortcut(vcc, NULL); + dev_kfree_skb_any(skb); + return; + } + + /* + * See if ingress MPC is using shortcut we opened as a return channel. + * This means we have a bi-directional vcc opened by us. + */ + if (eg->shortcut == NULL) { + eg->shortcut = vcc; + printk("mpoa: (%s) mpc_push: egress SVC in use\n", dev->name); + } + + skb_pull(skb, sizeof(struct llc_snap_hdr) + sizeof(tag)); /* get rid of LLC/SNAP header */ + new_skb = skb_realloc_headroom(skb, eg->ctrl_info.DH_length); /* LLC/SNAP is shorter than MAC header :( */ + dev_kfree_skb_any(skb); + if (new_skb == NULL){ + mpc->eg_ops->put(eg); + return; + } + skb_push(new_skb, eg->ctrl_info.DH_length); /* add MAC header */ + memcpy(new_skb->data, eg->ctrl_info.DLL_header, eg->ctrl_info.DH_length); + new_skb->protocol = eth_type_trans(new_skb, dev); + new_skb->nh.raw = new_skb->data; eg->latest_ip_addr = new_skb->nh.iph->saddr; - eg->packets_rcvd++; - - netif_rx(new_skb); + eg->packets_rcvd++; + mpc->eg_ops->put(eg); + + netif_rx(new_skb); - return; + return; } static struct atmdev_ops mpc_ops = { /* only send is required */ - close: mpoad_close, - send: msg_from_mpoad + close: mpoad_close, + send: msg_from_mpoad }; static struct atm_dev mpc_dev = { - &mpc_ops, /* device operations */ - NULL, /* PHY operations */ - "mpc", /* device type name */ - 42, /* device index (dummy) */ - NULL, /* VCC table */ - NULL, /* last VCC */ - NULL, /* per-device data */ - NULL, /* private PHY data */ - { 0 }, /* device flags */ - NULL, /* local ATM address */ - { 0 } /* no ESI */ - /* rest of the members will be 0 */ + &mpc_ops, /* device operations */ + NULL, /* PHY operations */ + "mpc", /* device type name */ + 42, /* device index (dummy) */ + NULL, /* VCC table */ + NULL, /* last VCC */ + NULL, /* per-device data */ + NULL, /* private PHY data */ + { 0 }, /* device flags */ + NULL, /* local ATM address */ + { 0 } /* no ESI */ + /* rest of the members will be 0 */ }; int atm_mpoa_mpoad_attach (struct atm_vcc *vcc, int arg) { - struct mpoa_client *mpc; - struct lec_priv *priv; - - if (mpcs == NULL) { - init_timer(&mpc_timer); - mpc_timer_refresh(); - - /* This lets us now how our LECs are doing */ - register_netdevice_notifier(&mpoa_notifier); - } - - mpc = find_mpc_by_itfnum(arg); - if (mpc == NULL) { - dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg); - mpc = alloc_mpc(); - mpc->dev_num = arg; - mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */ - } - if (mpc->mpoad_vcc) { - printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg); - return -EADDRINUSE; - } - - if (mpc->dev) { /* check if the lec is LANE2 capable */ - priv = (struct lec_priv *)mpc->dev->priv; - if (priv->lane_version < 2) - mpc->dev = NULL; + struct mpoa_client *mpc; + struct lec_priv *priv; + + if (mpcs == NULL) { + init_timer(&mpc_timer); + mpc_timer_refresh(); + + /* This lets us now how our LECs are doing */ + register_netdevice_notifier(&mpoa_notifier); + } + + mpc = find_mpc_by_itfnum(arg); + if (mpc == NULL) { + dprintk("mpoa: mpoad_attach: allocating new mpc for itf %d\n", arg); + mpc = alloc_mpc(); + mpc->dev_num = arg; + mpc->dev = find_lec_by_itfnum(arg); /* NULL if there was no lec */ + } + if (mpc->mpoad_vcc) { + printk("mpoa: mpoad_attach: mpoad is already present for itf %d\n", arg); + return -EADDRINUSE; + } + + if (mpc->dev) { /* check if the lec is LANE2 capable */ + priv = (struct lec_priv *)mpc->dev->priv; + if (priv->lane_version < 2) + mpc->dev = NULL; else - priv->lane2_ops->associate_indicator = lane2_assoc_ind; - } + priv->lane2_ops->associate_indicator = lane2_assoc_ind; + } - mpc->mpoad_vcc = vcc; - bind_vcc(vcc, &mpc_dev); + mpc->mpoad_vcc = vcc; + bind_vcc(vcc, &mpc_dev); set_bit(ATM_VF_META,&vcc->flags); set_bit(ATM_VF_READY,&vcc->flags); - if (mpc->dev) { - char empty[ATM_ESA_LEN]; - memset(empty, 0, ATM_ESA_LEN); - - start_mpc(mpc, mpc->dev); - /* set address if mpcd e.g. gets killed and restarted. - * If we do not do it now we have to wait for the next LE_ARP - */ - if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 ) - send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc); - } - - MOD_INC_USE_COUNT; - return arg; + if (mpc->dev) { + char empty[ATM_ESA_LEN]; + memset(empty, 0, ATM_ESA_LEN); + + start_mpc(mpc, mpc->dev); + /* set address if mpcd e.g. gets killed and restarted. + * If we do not do it now we have to wait for the next LE_ARP + */ + if ( memcmp(mpc->mps_ctrl_addr, empty, ATM_ESA_LEN) != 0 ) + send_set_mps_ctrl_addr(mpc->mps_ctrl_addr, mpc); + } + + MOD_INC_USE_COUNT; + return arg; } static void send_set_mps_ctrl_addr(char *addr, struct mpoa_client *mpc) { - struct k_message mesg; + struct k_message mesg; - memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN); - - mesg.type = SET_MPS_CTRL_ADDR; - memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN); - msg_to_mpoad(&mesg, mpc); + memcpy (mpc->mps_ctrl_addr, addr, ATM_ESA_LEN); + + mesg.type = SET_MPS_CTRL_ADDR; + memcpy(mesg.MPS_ctrl, addr, ATM_ESA_LEN); + msg_to_mpoad(&mesg, mpc); - return; + return; } static void mpoad_close(struct atm_vcc *vcc) { - unsigned long flags; - struct mpoa_client *mpc; - struct sk_buff *skb; - - mpc = find_mpc_by_vcc(vcc); - if (mpc == NULL) { - printk("mpoa: mpoad_close: did not find MPC\n"); - return; - } - if (!mpc->mpoad_vcc) { - printk("mpoa: mpoad_close: close for non-present mpoad\n"); - return; - } - - mpc->mpoad_vcc = NULL; - if (mpc->dev) { - struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv; - priv->lane2_ops->associate_indicator = NULL; - stop_mpc(mpc); - } - - /* clear the caches */ - write_lock_irqsave(&mpc->ingress_lock, flags); - while(mpc->in_ops->cache_remove(mpc->in_cache, mpc)); - write_unlock_irqrestore(&mpc->ingress_lock, flags); - - write_lock_irqsave(&mpc->egress_lock, flags); - while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc)); - write_unlock_irqrestore(&mpc->egress_lock, flags); + struct mpoa_client *mpc; + struct sk_buff *skb; + + mpc = find_mpc_by_vcc(vcc); + if (mpc == NULL) { + printk("mpoa: mpoad_close: did not find MPC\n"); + return; + } + if (!mpc->mpoad_vcc) { + printk("mpoa: mpoad_close: close for non-present mpoad\n"); + return; + } + + mpc->mpoad_vcc = NULL; + if (mpc->dev) { + struct lec_priv *priv = (struct lec_priv *)mpc->dev->priv; + priv->lane2_ops->associate_indicator = NULL; + stop_mpc(mpc); + } + + mpc->in_ops->destroy_cache(mpc); + mpc->eg_ops->destroy_cache(mpc); while ( (skb = skb_dequeue(&vcc->recvq)) ){ - atm_return(vcc, skb->truesize); - kfree_skb(skb); - } - - printk("mpoa: (%s) going down\n", - (mpc->dev) ? mpc->dev->name : "<unknown>"); - MOD_DEC_USE_COUNT; - - return; + atm_return(vcc, skb->truesize); + kfree_skb(skb); + } + + printk("mpoa: (%s) going down\n", + (mpc->dev) ? mpc->dev->name : "<unknown>"); + MOD_DEC_USE_COUNT; + + return; } /* @@ -862,163 +864,163 @@ static void mpoad_close(struct atm_vcc *vcc) */ static int msg_from_mpoad(struct atm_vcc *vcc, struct sk_buff *skb) { - - struct mpoa_client *mpc = find_mpc_by_vcc(vcc); - struct k_message *mesg = (struct k_message*)skb->data; - atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse); - - if (mpc == NULL) { - printk("mpoa: msg_from_mpoad: no mpc found\n"); - return 0; - } - dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>"); - switch(mesg->type) { - case MPOA_RES_REPLY_RCVD: - dprintk(" mpoa_res_reply_rcvd\n"); - MPOA_res_reply_rcvd(mesg, mpc); - break; - case MPOA_TRIGGER_RCVD: - dprintk(" mpoa_trigger_rcvd\n"); - MPOA_trigger_rcvd(mesg, mpc); - break; - case INGRESS_PURGE_RCVD: - dprintk(" nhrp_purge_rcvd\n"); - ingress_purge_rcvd(mesg, mpc); - break; - case EGRESS_PURGE_RCVD: - dprintk(" egress_purge_reply_rcvd\n"); - egress_purge_rcvd(mesg, mpc); - break; - case MPS_DEATH: - dprintk(" mps_death\n"); - mps_death(mesg, mpc); - break; - case CACHE_IMPOS_RCVD: - dprintk(" cache_impos_rcvd\n"); - MPOA_cache_impos_rcvd(mesg, mpc); - break; - case SET_MPC_CTRL_ADDR: - dprintk(" set_mpc_ctrl_addr\n"); - set_mpc_ctrl_addr_rcvd(mesg, mpc); - break; + + struct mpoa_client *mpc = find_mpc_by_vcc(vcc); + struct k_message *mesg = (struct k_message*)skb->data; + atomic_sub(skb->truesize+ATM_PDU_OVHD, &vcc->tx_inuse); + + if (mpc == NULL) { + printk("mpoa: msg_from_mpoad: no mpc found\n"); + return 0; + } + dprintk("mpoa: (%s) msg_from_mpoad:", (mpc->dev) ? mpc->dev->name : "<unknown>"); + switch(mesg->type) { + case MPOA_RES_REPLY_RCVD: + dprintk(" mpoa_res_reply_rcvd\n"); + MPOA_res_reply_rcvd(mesg, mpc); + break; + case MPOA_TRIGGER_RCVD: + dprintk(" mpoa_trigger_rcvd\n"); + MPOA_trigger_rcvd(mesg, mpc); + break; + case INGRESS_PURGE_RCVD: + dprintk(" nhrp_purge_rcvd\n"); + ingress_purge_rcvd(mesg, mpc); + break; + case EGRESS_PURGE_RCVD: + dprintk(" egress_purge_reply_rcvd\n"); + egress_purge_rcvd(mesg, mpc); + break; + case MPS_DEATH: + dprintk(" mps_death\n"); + mps_death(mesg, mpc); + break; + case CACHE_IMPOS_RCVD: + dprintk(" cache_impos_rcvd\n"); + MPOA_cache_impos_rcvd(mesg, mpc); + break; + case SET_MPC_CTRL_ADDR: + dprintk(" set_mpc_ctrl_addr\n"); + set_mpc_ctrl_addr_rcvd(mesg, mpc); + break; case SET_MPS_MAC_ADDR: - dprintk(" set_mps_mac_addr\n"); + dprintk(" set_mps_mac_addr\n"); set_mps_mac_addr_rcvd(mesg, mpc); break; case CLEAN_UP_AND_EXIT: - dprintk(" clean_up_and_exit\n"); - clean_up(mesg, mpc, DIE); - break; - case RELOAD: - dprintk(" reload\n"); - clean_up(mesg, mpc, RELOAD); - break; - case SET_MPC_PARAMS: - dprintk(" set_mpc_params\n"); - mpc->parameters = mesg->content.params; - break; - default: - dprintk(" unknown message %d\n", mesg->type); - break; - } - kfree_skb(skb); - - return 0; + dprintk(" clean_up_and_exit\n"); + clean_up(mesg, mpc, DIE); + break; + case RELOAD: + dprintk(" reload\n"); + clean_up(mesg, mpc, RELOAD); + break; + case SET_MPC_PARAMS: + dprintk(" set_mpc_params\n"); + mpc->parameters = mesg->content.params; + break; + default: + dprintk(" unknown message %d\n", mesg->type); + break; + } + kfree_skb(skb); + + return 0; } +/* Remember that this function may not do things that sleep */ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc) { - struct sk_buff *skb; - - if (mpc == NULL || !mpc->mpoad_vcc) { - printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type); - return -ENXIO; - } - - skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); - if (skb == NULL) - return -ENOMEM; - skb_put(skb, sizeof(struct k_message)); - memcpy(skb->data, mesg, sizeof(struct k_message)); - atm_force_charge(mpc->mpoad_vcc, skb->truesize); - skb_queue_tail(&mpc->mpoad_vcc->recvq, skb); - wake_up(&mpc->mpoad_vcc->sleep); - - return 0; + struct sk_buff *skb; + + if (mpc == NULL || !mpc->mpoad_vcc) { + printk("mpoa: msg_to_mpoad: mesg %d to a non-existent mpoad\n", mesg->type); + return -ENXIO; + } + + skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); + if (skb == NULL) + return -ENOMEM; + skb_put(skb, sizeof(struct k_message)); + memcpy(skb->data, mesg, sizeof(struct k_message)); + atm_force_charge(mpc->mpoad_vcc, skb->truesize); + skb_queue_tail(&mpc->mpoad_vcc->recvq, skb); + wake_up(&mpc->mpoad_vcc->sleep); + + return 0; } static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned long event, void *dev_ptr) { - struct net_device *dev; - struct mpoa_client *mpc; - struct lec_priv *priv; - - dev = (struct net_device *)dev_ptr; - if (dev->name == NULL || strncmp(dev->name, "lec", 3)) - return NOTIFY_DONE; /* we are only interested in lec:s */ - - switch (event) { - case NETDEV_REGISTER: /* a new lec device was allocated */ - priv = (struct lec_priv *)dev->priv; - if (priv->lane_version < 2) - break; - priv->lane2_ops->associate_indicator = lane2_assoc_ind; - mpc = find_mpc_by_itfnum(priv->itfnum); - if (mpc == NULL) { - dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n", - dev->name); - mpc = alloc_mpc(); - if (mpc == NULL) { - printk("mpoa: mpoa_event_listener: no new mpc"); - break; - } - } - mpc->dev_num = priv->itfnum; - mpc->dev = dev; - dprintk("mpoa: (%s) was initialized\n", dev->name); - break; - case NETDEV_UNREGISTER: - /* the lec device was deallocated */ - mpc = find_mpc_by_lec(dev); - if (mpc == NULL) - break; - dprintk("mpoa: device (%s) was deallocated\n", dev->name); - stop_mpc(mpc); - mpc->dev = NULL; - break; - case NETDEV_UP: - /* the dev was ifconfig'ed up */ - mpc = find_mpc_by_lec(dev); - if (mpc == NULL) - break; - if (mpc->mpoad_vcc != NULL) { - start_mpc(mpc, dev); - } - break; - case NETDEV_DOWN: - /* the dev was ifconfig'ed down */ - /* this means dev->start == 0 and - * the flow of packets from the - * upper layer stops - */ - mpc = find_mpc_by_lec(dev); - if (mpc == NULL) - break; - if (mpc->mpoad_vcc != NULL) { - stop_mpc(mpc); - } - break; - case NETDEV_REBOOT: - case NETDEV_CHANGE: - case NETDEV_CHANGEMTU: - case NETDEV_CHANGEADDR: - case NETDEV_GOING_DOWN: - break; - default: - break; - } - - return NOTIFY_DONE; + struct net_device *dev; + struct mpoa_client *mpc; + struct lec_priv *priv; + + dev = (struct net_device *)dev_ptr; + if (dev->name == NULL || strncmp(dev->name, "lec", 3)) + return NOTIFY_DONE; /* we are only interested in lec:s */ + + switch (event) { + case NETDEV_REGISTER: /* a new lec device was allocated */ + priv = (struct lec_priv *)dev->priv; + if (priv->lane_version < 2) + break; + priv->lane2_ops->associate_indicator = lane2_assoc_ind; + mpc = find_mpc_by_itfnum(priv->itfnum); + if (mpc == NULL) { + dprintk("mpoa: mpoa_event_listener: allocating new mpc for %s\n", + dev->name); + mpc = alloc_mpc(); + if (mpc == NULL) { + printk("mpoa: mpoa_event_listener: no new mpc"); + break; + } + } + mpc->dev_num = priv->itfnum; + mpc->dev = dev; + dprintk("mpoa: (%s) was initialized\n", dev->name); + break; + case NETDEV_UNREGISTER: + /* the lec device was deallocated */ + mpc = find_mpc_by_lec(dev); + if (mpc == NULL) + break; + dprintk("mpoa: device (%s) was deallocated\n", dev->name); + stop_mpc(mpc); + mpc->dev = NULL; + break; + case NETDEV_UP: + /* the dev was ifconfig'ed up */ + mpc = find_mpc_by_lec(dev); + if (mpc == NULL) + break; + if (mpc->mpoad_vcc != NULL) { + start_mpc(mpc, dev); + } + break; + case NETDEV_DOWN: + /* the dev was ifconfig'ed down */ + /* this means that the flow of packets from the + * upper layer stops + */ + mpc = find_mpc_by_lec(dev); + if (mpc == NULL) + break; + if (mpc->mpoad_vcc != NULL) { + stop_mpc(mpc); + } + break; + case NETDEV_REBOOT: + case NETDEV_CHANGE: + case NETDEV_CHANGEMTU: + case NETDEV_CHANGEADDR: + case NETDEV_GOING_DOWN: + break; + default: + break; + } + + return NOTIFY_DONE; } /* @@ -1027,33 +1029,36 @@ static int mpoa_event_listener(struct notifier_block *mpoa_notifier, unsigned lo */ -static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client) +static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - uint32_t dst_ip = msg->content.in_info.in_dst_ip; - in_cache_entry *entry; + uint32_t dst_ip = msg->content.in_info.in_dst_ip; + in_cache_entry *entry; - entry = client->in_ops->search(dst_ip, client); - if( entry == NULL ){ - entry = client->in_ops->new_entry(dst_ip, client); - entry->entry_state = INGRESS_RESOLVING; + entry = mpc->in_ops->get(dst_ip, mpc); + if(entry == NULL){ + entry = mpc->in_ops->add_entry(dst_ip, mpc); + entry->entry_state = INGRESS_RESOLVING; msg->type = SND_MPOA_RES_RQST; - msg->content.in_info = entry->ctrl_info; - msg_to_mpoad(msg,client); + msg->content.in_info = entry->ctrl_info; + msg_to_mpoad(msg, mpc); do_gettimeofday(&(entry->reply_wait)); + mpc->in_ops->put(entry); return; - } - - if( entry->entry_state == INGRESS_INVALID ){ - entry->entry_state = INGRESS_RESOLVING; + } + + if(entry->entry_state == INGRESS_INVALID){ + entry->entry_state = INGRESS_RESOLVING; msg->type = SND_MPOA_RES_RQST; - msg->content.in_info = entry->ctrl_info; - msg_to_mpoad(msg,client); + msg->content.in_info = entry->ctrl_info; + msg_to_mpoad(msg, mpc); do_gettimeofday(&(entry->reply_wait)); - return; - } - - printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n", - (client->dev) ? client->dev->name : "<unknown>"); + mpc->in_ops->put(entry); + return; + } + + printk("mpoa: (%s) MPOA_trigger_rcvd: entry already in resolving state\n", + (mpc->dev) ? mpc->dev->name : "<unknown>"); + mpc->in_ops->put(entry); return; } @@ -1061,30 +1066,36 @@ static void MPOA_trigger_rcvd(struct k_message *msg, struct mpoa_client *client) * Things get complicated because we have to check if there's an egress * shortcut with suitable traffic parameters we could use. */ -static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry){ - uint32_t dst_ip = msg->content.in_info.in_dst_ip; - unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip; +static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_client *client, in_cache_entry *entry) +{ + uint32_t dst_ip = msg->content.in_info.in_dst_ip; + unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip; struct atm_mpoa_qos *qos = atm_mpoa_search_qos(dst_ip); - eg_cache_entry *eg_entry = client->eg_ops->search_by_src_ip(dst_ip, client); + eg_cache_entry *eg_entry = client->eg_ops->get_by_src_ip(dst_ip, client); + if(eg_entry && eg_entry->shortcut){ - if(eg_entry->shortcut->qos.txtp.traffic_class & + if(eg_entry->shortcut->qos.txtp.traffic_class & msg->qos.txtp.traffic_class & (qos ? qos->qos.txtp.traffic_class : ATM_UBR | ATM_CBR)){ - if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR) - entry->shortcut = eg_entry->shortcut; + if(eg_entry->shortcut->qos.txtp.traffic_class == ATM_UBR) + entry->shortcut = eg_entry->shortcut; else if(eg_entry->shortcut->qos.txtp.max_pcr > 0) - entry->shortcut = eg_entry->shortcut; + entry->shortcut = eg_entry->shortcut; } if(entry->shortcut){ - dprintk("mpoa: (%s) using egress SVC to reach %d.%d.%d.%d\n",client->dev->name, ip[0], ip[1], ip[2], ip[3]); + dprintk("mpoa: (%s) using egress SVC to reach %u.%u.%u.%u\n",client->dev->name, NIPQUAD(ip)); + client->eg_ops->put(eg_entry); return; } } + if (eg_entry != NULL) + client->eg_ops->put(eg_entry); + /* No luck in the egress cache we must open an ingress SVC */ msg->type = OPEN_INGRESS_SVC; if (qos && (qos->qos.txtp.traffic_class == msg->qos.txtp.traffic_class)) { - msg->qos = qos->qos; + msg->qos = qos->qos; printk("mpoa: (%s) trying to get a CBR shortcut\n",client->dev->name); } else memset(&msg->qos,0,sizeof(struct atm_qos)); @@ -1092,45 +1103,49 @@ static void check_qos_and_open_shortcut(struct k_message *msg, struct mpoa_clien return; } -static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *client) +static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *mpc) { unsigned char *ip; - uint32_t dst_ip = msg->content.in_info.in_dst_ip; - in_cache_entry *entry = client->in_ops->search(dst_ip, client); + uint32_t dst_ip = msg->content.in_info.in_dst_ip; + in_cache_entry *entry = mpc->in_ops->get(dst_ip, mpc); ip = (unsigned char *)&dst_ip; - dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %d.%d.%d.%d\n", client->dev->name, ip[0], ip[1], ip[2], ip[3]); - ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", client->dev->name, entry); - if(entry == NULL){ - printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", client->dev->name); - return; - } - ddprintk(" entry_state = %d ", entry->entry_state); - - if (entry->entry_state == INGRESS_RESOLVED) { - printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", client->dev->name); - return; - } - - entry->ctrl_info = msg->content.in_info; - do_gettimeofday(&(entry->tv)); - do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */ - entry->refresh_time = 0; - ddprintk("entry->shortcut = %p\n", entry->shortcut); + dprintk("mpoa: (%s) MPOA_res_reply_rcvd: ip %u.%u.%u.%u\n", mpc->dev->name, NIPQUAD(ip)); + ddprintk("mpoa: (%s) MPOA_res_reply_rcvd() entry = %p", mpc->dev->name, entry); + if(entry == NULL){ + printk("\nmpoa: (%s) ARGH, received res. reply for an entry that doesn't exist.\n", mpc->dev->name); + return; + } + ddprintk(" entry_state = %d ", entry->entry_state); + + if (entry->entry_state == INGRESS_RESOLVED) { + printk("\nmpoa: (%s) MPOA_res_reply_rcvd for RESOLVED entry!\n", mpc->dev->name); + mpc->in_ops->put(entry); + return; + } + + entry->ctrl_info = msg->content.in_info; + do_gettimeofday(&(entry->tv)); + do_gettimeofday(&(entry->reply_wait)); /* Used in refreshing func from now on */ + entry->refresh_time = 0; + ddprintk("entry->shortcut = %p\n", entry->shortcut); if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL){ - entry->entry_state = INGRESS_RESOLVED; + entry->entry_state = INGRESS_RESOLVED; + mpc->in_ops->put(entry); return; /* Shortcut already open... */ } if (entry->shortcut != NULL) { printk("mpoa: (%s) MPOA_res_reply_rcvd: entry->shortcut != NULL, impossible!\n", - client->dev->name); + mpc->dev->name); + mpc->in_ops->put(entry); return; } - check_qos_and_open_shortcut(msg, client, entry); + check_qos_and_open_shortcut(msg, mpc, entry); entry->entry_state = INGRESS_RESOLVED; + mpc->in_ops->put(entry); return; @@ -1138,73 +1153,79 @@ static void MPOA_res_reply_rcvd(struct k_message *msg, struct mpoa_client *clien static void ingress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - uint32_t dst_ip = msg->content.in_info.in_dst_ip; - uint32_t mask = msg->ip_mask; + uint32_t dst_ip = msg->content.in_info.in_dst_ip; + uint32_t mask = msg->ip_mask; unsigned char *ip = (unsigned char *)&dst_ip; + in_cache_entry *entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask); - in_cache_entry *entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask); - if( entry == NULL ){ - printk("mpoa: (%s) ingress_purge_rcvd: recieved a purge for an entry that doesn't exist, ", mpc->dev->name); - printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]); - return; - } - while(entry != NULL){ - dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" , - mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); - mpc->in_ops->cache_remove(entry, mpc); - entry = mpc->in_ops->search_with_mask(dst_ip, mpc, mask); + if(entry == NULL){ + printk("mpoa: (%s) ingress_purge_rcvd: purge for a non-existing entry, ", mpc->dev->name); + printk("ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]); + return; } - return; + + do { + dprintk("mpoa: (%s) ingress_purge_rcvd: removing an ingress entry, ip = %u.%u.%u.%u\n" , + mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); + write_lock_bh(&mpc->ingress_lock); + mpc->in_ops->remove_entry(entry, mpc); + write_unlock_bh(&mpc->ingress_lock); + mpc->in_ops->put(entry); + entry = mpc->in_ops->get_with_mask(dst_ip, mpc, mask); + } while (entry != NULL); + + return; } static void egress_purge_rcvd(struct k_message *msg, struct mpoa_client *mpc) { - unsigned long flags; - uint32_t cache_id = msg->content.eg_info.cache_id; - eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(cache_id, mpc); - - if( entry == NULL ){ - printk("mpoa: (%s) egress_purge_rcvd: received a purge reply for an entry that doesn't exist\n", mpc->dev->name); - return; - } - - write_lock_irqsave(&mpc->egress_lock, flags); - mpc->eg_ops->cache_remove(entry, mpc); - write_unlock_irqrestore(&mpc->egress_lock, flags); - - return; + uint32_t cache_id = msg->content.eg_info.cache_id; + eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(cache_id, mpc); + + if (entry == NULL) { + dprintk("mpoa: (%s) egress_purge_rcvd: purge for a non-existing entry\n", mpc->dev->name); + return; + } + + write_lock_irq(&mpc->egress_lock); + mpc->eg_ops->remove_entry(entry, mpc); + write_unlock_irq(&mpc->egress_lock); + + mpc->eg_ops->put(entry); + + return; } static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) { - struct k_message *purge_msg; - struct sk_buff *skb; - - dprintk("mpoa: purge_egress_shortcut: entering\n"); - if (vcc == NULL) { - printk("mpoa: purge_egress_shortcut: vcc == NULL\n"); - return; - } - - skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); - if (skb == NULL) { - printk("mpoa: purge_egress_shortcut: out of memory\n"); - return; - } - - skb_put(skb, sizeof(struct k_message)); - memset(skb->data, 0, sizeof(struct k_message)); - purge_msg = (struct k_message *)skb->data; - purge_msg->type = DATA_PLANE_PURGE; - if (entry != NULL) - purge_msg->content.eg_info = entry->ctrl_info; - - atm_force_charge(vcc, skb->truesize); - skb_queue_tail(&vcc->recvq, skb); - wake_up(&vcc->sleep); - dprintk("mpoa: purge_egress_shortcut: exiting:\n"); - - return; + struct k_message *purge_msg; + struct sk_buff *skb; + + dprintk("mpoa: purge_egress_shortcut: entering\n"); + if (vcc == NULL) { + printk("mpoa: purge_egress_shortcut: vcc == NULL\n"); + return; + } + + skb = alloc_skb(sizeof(struct k_message), GFP_ATOMIC); + if (skb == NULL) { + printk("mpoa: purge_egress_shortcut: out of memory\n"); + return; + } + + skb_put(skb, sizeof(struct k_message)); + memset(skb->data, 0, sizeof(struct k_message)); + purge_msg = (struct k_message *)skb->data; + purge_msg->type = DATA_PLANE_PURGE; + if (entry != NULL) + purge_msg->content.eg_info = entry->ctrl_info; + + atm_force_charge(vcc, skb->truesize); + skb_queue_tail(&vcc->recvq, skb); + wake_up(&vcc->sleep); + dprintk("mpoa: purge_egress_shortcut: exiting:\n"); + + return; } /* @@ -1213,104 +1234,102 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) */ static void mps_death( struct k_message * msg, struct mpoa_client * mpc ) { + eg_cache_entry *entry; - unsigned long flags; - eg_cache_entry *entry; - - dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name); + dprintk("mpoa: (%s) mps_death:\n", mpc->dev->name); - if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){ - printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name); - return; - } - - entry = mpc->eg_cache; - while (entry != NULL) { - purge_egress_shortcut(entry->shortcut, entry); - entry = entry->next; - } + if(memcmp(msg->MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN)){ + printk("mpoa: (%s) mps_death: wrong MPS\n", mpc->dev->name); + return; + } - write_lock_irqsave(&mpc->ingress_lock, flags); - while(mpc->in_ops->cache_remove(mpc->in_cache, mpc)); - write_unlock_irqrestore(&mpc->ingress_lock, flags); + /* FIXME: This knows too much of the cache structure */ + read_lock_irq(&mpc->egress_lock); + entry = mpc->eg_cache; + while (entry != NULL) { + purge_egress_shortcut(entry->shortcut, entry); + entry = entry->next; + } + read_unlock_irq(&mpc->egress_lock); - write_lock_irqsave(&mpc->egress_lock, flags); - while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc)); - write_unlock_irqrestore(&mpc->egress_lock, flags); + mpc->in_ops->destroy_cache(mpc); + mpc->eg_ops->destroy_cache(mpc); - return; + return; } -static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc){ - - uint16_t holding_time; - unsigned long flags; - eg_cache_entry *entry = mpc->eg_ops->search_by_cache_id(msg->content.eg_info.cache_id, mpc); - - holding_time = msg->content.eg_info.holding_time; - dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n", - mpc->dev->name, entry, holding_time); - if(entry == NULL && holding_time) { - mpc->eg_ops->new_entry(msg, mpc); - return; - } - if(holding_time){ - mpc->eg_ops->update(entry, holding_time); - return; - } - - write_lock_irqsave(&mpc->egress_lock, flags); - mpc->eg_ops->cache_remove(entry, mpc); - write_unlock_irqrestore(&mpc->egress_lock, flags); - - - return; +static void MPOA_cache_impos_rcvd( struct k_message * msg, struct mpoa_client * mpc) +{ + uint16_t holding_time; + eg_cache_entry *entry = mpc->eg_ops->get_by_cache_id(msg->content.eg_info.cache_id, mpc); + + holding_time = msg->content.eg_info.holding_time; + dprintk("mpoa: (%s) MPOA_cache_impos_rcvd: entry = %p, holding_time = %u\n", + mpc->dev->name, entry, holding_time); + if(entry == NULL && holding_time) { + entry = mpc->eg_ops->add_entry(msg, mpc); + mpc->eg_ops->put(entry); + return; + } + if(holding_time){ + mpc->eg_ops->update(entry, holding_time); + return; + } + + write_lock_irq(&mpc->egress_lock); + mpc->eg_ops->remove_entry(entry, mpc); + write_unlock_irq(&mpc->egress_lock); + + mpc->eg_ops->put(entry); + + return; } static void set_mpc_ctrl_addr_rcvd(struct k_message *mesg, struct mpoa_client *mpc) { - struct lec_priv *priv; - int i, retval ; - - uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN]; - - tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */ - tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */ - tlv[5] = 0x02; /* MPOA client */ - tlv[6] = 0x00; /* number of MPS MAC addresses */ - - memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */ - memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN); - - dprintk("mpoa: (%s) setting MPC ctrl ATM address to ", - (mpc->dev) ? mpc->dev->name : "<unknown>"); - for (i = 7; i < sizeof(tlv); i++) - dprintk("%02x ", tlv[i]); - dprintk("\n"); - - if (mpc->dev) { - priv = (struct lec_priv *)mpc->dev->priv; - retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv)); - if (retval == 0) - printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name); - retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL); - if (retval < 0) - printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name); - } - - return; + struct lec_priv *priv; + int i, retval ; + + uint8_t tlv[4 + 1 + 1 + 1 + ATM_ESA_LEN]; + + tlv[0] = 00; tlv[1] = 0xa0; tlv[2] = 0x3e; tlv[3] = 0x2a; /* type */ + tlv[4] = 1 + 1 + ATM_ESA_LEN; /* length */ + tlv[5] = 0x02; /* MPOA client */ + tlv[6] = 0x00; /* number of MPS MAC addresses */ + + memcpy(&tlv[7], mesg->MPS_ctrl, ATM_ESA_LEN); /* MPC ctrl ATM addr */ + memcpy(mpc->our_ctrl_addr, mesg->MPS_ctrl, ATM_ESA_LEN); + + dprintk("mpoa: (%s) setting MPC ctrl ATM address to ", + (mpc->dev) ? mpc->dev->name : "<unknown>"); + for (i = 7; i < sizeof(tlv); i++) + dprintk("%02x ", tlv[i]); + dprintk("\n"); + + if (mpc->dev) { + priv = (struct lec_priv *)mpc->dev->priv; + retval = priv->lane2_ops->associate_req(mpc->dev, mpc->dev->dev_addr, tlv, sizeof(tlv)); + if (retval == 0) + printk("mpoa: (%s) MPOA device type TLV association failed\n", mpc->dev->name); + retval = priv->lane2_ops->resolve(mpc->dev, NULL, 1, NULL, NULL); + if (retval < 0) + printk("mpoa: (%s) targetless LE_ARP request failed\n", mpc->dev->name); + } + + return; } -static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client){ +static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *client) +{ - if(client->number_of_mps_macs) - kfree(client->mps_macs); - client->number_of_mps_macs = 0; + if(client->number_of_mps_macs) + kfree(client->mps_macs); + client->number_of_mps_macs = 0; client->mps_macs = kmalloc(ETH_ALEN,GFP_KERNEL); - if (client->mps_macs == NULL) { - printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n"); - return; - } + if (client->mps_macs == NULL) { + printk("mpoa: set_mps_mac_addr_rcvd: out of memory\n"); + return; + } client->number_of_mps_macs = 1; memcpy(client->mps_macs, msg->MPS_ctrl, ETH_ALEN); @@ -1320,22 +1339,23 @@ static void set_mps_mac_addr_rcvd(struct k_message *msg, struct mpoa_client *cli /* * purge egress cache and tell daemon to 'action' (DIE, RELOAD) */ -static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action){ +static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action) +{ - unsigned long flags; - eg_cache_entry *entry; + eg_cache_entry *entry; msg->type = SND_EGRESS_PURGE; - read_lock_irqsave(&mpc->egress_lock, flags); - entry = mpc->eg_cache; - while(entry != NULL){ - msg->content.eg_info = entry->ctrl_info; - dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id); + /* FIXME: This knows too much of the cache structure */ + read_lock_irq(&mpc->egress_lock); + entry = mpc->eg_cache; + while (entry != NULL){ + msg->content.eg_info = entry->ctrl_info; + dprintk("mpoa: cache_id %u\n", entry->ctrl_info.cache_id); msg_to_mpoad(msg, mpc); entry = entry->next; } - read_unlock_irqrestore(&mpc->egress_lock, flags); + read_unlock_irq(&mpc->egress_lock); msg->type = action; msg_to_mpoad(msg, mpc); @@ -1344,116 +1364,116 @@ static void clean_up(struct k_message *msg, struct mpoa_client *mpc, int action) static void mpc_timer_refresh() { - mpc_timer.expires = jiffies + (MPC_P2 * HZ); - mpc_timer.data = mpc_timer.expires; - mpc_timer.function = mpc_cache_check; - add_timer(&mpc_timer); - - return; + mpc_timer.expires = jiffies + (MPC_P2 * HZ); + mpc_timer.data = mpc_timer.expires; + mpc_timer.function = mpc_cache_check; + add_timer(&mpc_timer); + + return; } static void mpc_cache_check( unsigned long checking_time ) { - struct mpoa_client *mpc = mpcs; - static unsigned long previous_resolving_check_time = 0; - static unsigned long previous_refresh_time = 0; - - while( mpc != NULL ){ - mpc->in_ops->clear_count(mpc); + struct mpoa_client *mpc = mpcs; + static unsigned long previous_resolving_check_time = 0; + static unsigned long previous_refresh_time = 0; + + while( mpc != NULL ){ + mpc->in_ops->clear_count(mpc); mpc->eg_ops->clear_expired(mpc); - if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){ - mpc->in_ops->check_resolving(mpc); - previous_resolving_check_time = checking_time; - } - if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){ - mpc->in_ops->refresh(mpc); - previous_refresh_time = checking_time; - } - mpc = mpc->next; - } - mpc_timer_refresh(); - - return; + if(checking_time - previous_resolving_check_time > mpc->parameters.mpc_p4 * HZ ){ + mpc->in_ops->check_resolving(mpc); + previous_resolving_check_time = checking_time; + } + if(checking_time - previous_refresh_time > mpc->parameters.mpc_p5 * HZ ){ + mpc->in_ops->refresh(mpc); + previous_refresh_time = checking_time; + } + mpc = mpc->next; + } + mpc_timer_refresh(); + + return; } void atm_mpoa_init_ops(struct atm_mpoa_ops *ops) { - ops->mpoad_attach = atm_mpoa_mpoad_attach; - ops->vcc_attach = atm_mpoa_vcc_attach; + ops->mpoad_attach = atm_mpoa_mpoad_attach; + ops->vcc_attach = atm_mpoa_vcc_attach; #ifdef CONFIG_PROC_FS if(mpc_proc_init() != 0) - printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n"); + printk(KERN_INFO "mpoa: failed to initialize /proc/mpoa\n"); else - printk(KERN_INFO "mpoa: /proc/mpoa initialized\n"); + printk(KERN_INFO "mpoa: /proc/mpoa initialized\n"); #endif - printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); + printk("mpc.c: " __DATE__ " " __TIME__ " initialized\n"); - return; + return; } #ifdef MODULE int init_module(void) { - extern struct atm_mpoa_ops atm_mpoa_ops; + extern struct atm_mpoa_ops atm_mpoa_ops; atm_mpoa_init_ops(&atm_mpoa_ops); - return 0; + return 0; } void cleanup_module(void) { - extern struct atm_mpoa_ops atm_mpoa_ops; - struct mpoa_client *mpc, *tmp; - struct atm_mpoa_qos *qos, *nextqos; - struct lec_priv *priv; - - if (MOD_IN_USE) { - printk("mpc.c: module in use\n"); - return; - } + extern struct atm_mpoa_ops atm_mpoa_ops; + struct mpoa_client *mpc, *tmp; + struct atm_mpoa_qos *qos, *nextqos; + struct lec_priv *priv; + + if (MOD_IN_USE) { + printk("mpc.c: module in use\n"); + return; + } #ifdef CONFIG_PROC_FS mpc_proc_clean(); #endif - del_timer(&mpc_timer); - unregister_netdevice_notifier(&mpoa_notifier); - atm_mpoa_ops.mpoad_attach = NULL; - atm_mpoa_ops.vcc_attach = NULL; - - mpc = mpcs; - mpcs = NULL; - while (mpc != NULL) { - tmp = mpc->next; - if (mpc->dev != NULL) { - stop_mpc(mpc); - priv = (struct lec_priv *)mpc->dev->priv; - if (priv->lane2_ops != NULL) - priv->lane2_ops->associate_indicator = NULL; - } - ddprintk("mpoa: cleanup_module: about to clear caches\n"); - while(mpc->in_ops->cache_remove(mpc->in_cache, mpc)); - while(mpc->eg_ops->cache_remove(mpc->eg_cache, mpc)); - ddprintk("mpoa: cleanup_module: caches cleared\n"); - kfree(mpc->mps_macs); - memset(mpc, 0, sizeof(struct mpoa_client)); - ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc); - kfree(mpc); - ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp); - mpc = tmp; - } - - qos = qos_head; - qos_head = NULL; - while (qos != NULL) { - nextqos = qos->next; - dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos); - kfree(qos); - qos = nextqos; - } - - return; + del_timer(&mpc_timer); + unregister_netdevice_notifier(&mpoa_notifier); + atm_mpoa_ops.mpoad_attach = NULL; + atm_mpoa_ops.vcc_attach = NULL; + + mpc = mpcs; + mpcs = NULL; + while (mpc != NULL) { + tmp = mpc->next; + if (mpc->dev != NULL) { + stop_mpc(mpc); + priv = (struct lec_priv *)mpc->dev->priv; + if (priv->lane2_ops != NULL) + priv->lane2_ops->associate_indicator = NULL; + } + ddprintk("mpoa: cleanup_module: about to clear caches\n"); + mpc->in_ops->destroy_cache(mpc); + mpc->eg_ops->destroy_cache(mpc); + ddprintk("mpoa: cleanup_module: caches cleared\n"); + kfree(mpc->mps_macs); + memset(mpc, 0, sizeof(struct mpoa_client)); + ddprintk("mpoa: cleanup_module: about to kfree %p\n", mpc); + kfree(mpc); + ddprintk("mpoa: cleanup_module: next mpc is at %p\n", tmp); + mpc = tmp; + } + + qos = qos_head; + qos_head = NULL; + while (qos != NULL) { + nextqos = qos->next; + dprintk("mpoa: cleanup_module: freeing qos entry %p\n", qos); + kfree(qos); + qos = nextqos; + } + + return; } #endif /* MODULE */ diff --git a/net/atm/mpoa_caches.c b/net/atm/mpoa_caches.c index 8b94fb055..0bca7aa6c 100644 --- a/net/atm/mpoa_caches.c +++ b/net/atm/mpoa_caches.c @@ -22,165 +22,159 @@ #define ddprintk(format,args...) #endif -static in_cache_entry *in_cache_search(uint32_t dst_ip, - struct mpoa_client *client) +static in_cache_entry *in_cache_get(uint32_t dst_ip, + struct mpoa_client *client) { - unsigned long flags; - in_cache_entry *entry; - - read_lock_irqsave(&client->ingress_lock, flags); - entry = client->in_cache; - while(entry != NULL){ - if( entry->ctrl_info.in_dst_ip == dst_ip ){ - read_unlock_irqrestore(&client->ingress_lock, flags); - return entry; - } - entry = entry->next; - } - read_unlock_irqrestore(&client->ingress_lock, flags); - - return NULL; + in_cache_entry *entry; + + read_lock_bh(&client->ingress_lock); + entry = client->in_cache; + while(entry != NULL){ + if( entry->ctrl_info.in_dst_ip == dst_ip ){ + atomic_inc(&entry->use); + read_unlock_bh(&client->ingress_lock); + return entry; + } + entry = entry->next; + } + read_unlock_bh(&client->ingress_lock); + + return NULL; } -static in_cache_entry *in_cache_search_with_mask(uint32_t dst_ip, - struct mpoa_client *client, - uint32_t mask){ - unsigned long flags; - in_cache_entry *entry; - - read_lock_irqsave(&client->ingress_lock, flags); - entry = client->in_cache; - while(entry != NULL){ - if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){ - read_unlock_irqrestore(&client->ingress_lock, flags); - return entry; - } - entry = entry->next; - } - read_unlock_irqrestore(&client->ingress_lock, flags); - - return NULL; - +static in_cache_entry *in_cache_get_with_mask(uint32_t dst_ip, + struct mpoa_client *client, + uint32_t mask) +{ + in_cache_entry *entry; + + read_lock_bh(&client->ingress_lock); + entry = client->in_cache; + while(entry != NULL){ + if((entry->ctrl_info.in_dst_ip & mask) == (dst_ip & mask )){ + atomic_inc(&entry->use); + read_unlock_bh(&client->ingress_lock); + return entry; + } + entry = entry->next; + } + read_unlock_bh(&client->ingress_lock); + + return NULL; + } -static in_cache_entry *in_cache_search_by_vcc(struct atm_vcc *vcc, - struct mpoa_client *client ) +static in_cache_entry *in_cache_get_by_vcc(struct atm_vcc *vcc, + struct mpoa_client *client ) { - unsigned long flags; - in_cache_entry *entry; - - read_lock_irqsave(&client->ingress_lock, flags); - entry = client->in_cache; - while(entry != NULL){ - if(entry->shortcut == vcc) { - read_unlock_irqrestore(&client->ingress_lock, flags); - return entry; - } + in_cache_entry *entry; + + read_lock_bh(&client->ingress_lock); + entry = client->in_cache; + while(entry != NULL){ + if(entry->shortcut == vcc) { + atomic_inc(&entry->use); + read_unlock_bh(&client->ingress_lock); + return entry; + } entry = entry->next; - } - read_unlock_irqrestore(&client->ingress_lock, flags); + } + read_unlock_bh(&client->ingress_lock); - return NULL; + return NULL; } -static in_cache_entry *new_in_cache_entry(uint32_t dst_ip, +static in_cache_entry *in_cache_add_entry(uint32_t dst_ip, struct mpoa_client *client) { - unsigned long flags; - unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip; - in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL); - - if (entry == NULL) { - printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n"); - return NULL; - } - - dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]); - memset(entry,0,sizeof(in_cache_entry)); - - dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n"); - write_lock_irqsave(&client->ingress_lock, flags); - entry->next = client->in_cache; - entry->prev = NULL; - if (client->in_cache != NULL) - client->in_cache->prev = entry; - client->in_cache = entry; - write_unlock_irqrestore(&client->ingress_lock, flags); - dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n"); - - memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN); - entry->ctrl_info.in_dst_ip = dst_ip; - do_gettimeofday(&(entry->tv)); - entry->retry_time = client->parameters.mpc_p4; - entry->count = 1; - entry->entry_state = INGRESS_INVALID; - entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT; + unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&dst_ip; + in_cache_entry* entry = kmalloc(sizeof(in_cache_entry), GFP_KERNEL); + + if (entry == NULL) { + printk("mpoa: mpoa_caches.c: new_in_cache_entry: out of memory\n"); + return NULL; + } + + dprintk("mpoa: mpoa_caches.c: adding an ingress entry, ip = %u.%u.%u.%u\n", ip[0], ip[1], ip[2], ip[3]); + memset(entry,0,sizeof(in_cache_entry)); + + atomic_set(&entry->use, 1); + dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: about to lock\n"); + write_lock_bh(&client->ingress_lock); + entry->next = client->in_cache; + entry->prev = NULL; + if (client->in_cache != NULL) + client->in_cache->prev = entry; + client->in_cache = entry; + + memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN); + entry->ctrl_info.in_dst_ip = dst_ip; + do_gettimeofday(&(entry->tv)); + entry->retry_time = client->parameters.mpc_p4; + entry->count = 1; + entry->entry_state = INGRESS_INVALID; + entry->ctrl_info.holding_time = HOLDING_TIME_DEFAULT; + atomic_inc(&entry->use); + + write_unlock_bh(&client->ingress_lock); + dprintk("mpoa: mpoa_caches.c: new_in_cache_entry: unlocked\n"); return entry; } -static int cache_hit( in_cache_entry * entry, struct mpoa_client *mpc) +static int cache_hit(in_cache_entry *entry, struct mpoa_client *mpc) { - struct atm_mpoa_qos *qos; - struct k_message msg; + struct atm_mpoa_qos *qos; + struct k_message msg; - entry->count++; + entry->count++; if(entry->entry_state == INGRESS_RESOLVED && entry->shortcut != NULL) - return OPEN; + return OPEN; if(entry->entry_state == INGRESS_REFRESHING){ - if(entry->count > mpc->parameters.mpc_p1){ - msg.type = SND_MPOA_RES_RQST; + if(entry->count > mpc->parameters.mpc_p1){ + msg.type = SND_MPOA_RES_RQST; msg.content.in_info = entry->ctrl_info; memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN); - qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); - if (qos != NULL) msg.qos = qos->qos; + qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); + if (qos != NULL) msg.qos = qos->qos; msg_to_mpoad(&msg, mpc); do_gettimeofday(&(entry->reply_wait)); entry->entry_state = INGRESS_RESOLVING; } if(entry->shortcut != NULL) - return OPEN; + return OPEN; return CLOSED; } - if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL) - return OPEN; + if(entry->entry_state == INGRESS_RESOLVING && entry->shortcut != NULL) + return OPEN; - if( entry->count > mpc->parameters.mpc_p1 && - entry->entry_state == INGRESS_INVALID){ - unsigned char *ip __attribute__ ((unused)) = + if( entry->count > mpc->parameters.mpc_p1 && + entry->entry_state == INGRESS_INVALID){ + unsigned char *ip __attribute__ ((unused)) = (unsigned char *)&entry->ctrl_info.in_dst_ip; dprintk("mpoa: (%s) mpoa_caches.c: threshold exceeded for ip %u.%u.%u.%u, sending MPOA res req\n", mpc->dev->name, ip[0], ip[1], ip[2], ip[3]); - entry->entry_state = INGRESS_RESOLVING; - msg.type = SND_MPOA_RES_RQST; - memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN ); - msg.content.in_info = entry->ctrl_info; - qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); - if (qos != NULL) msg.qos = qos->qos; - msg_to_mpoad( &msg, mpc); - do_gettimeofday(&(entry->reply_wait)); - } - - return CLOSED; + entry->entry_state = INGRESS_RESOLVING; + msg.type = SND_MPOA_RES_RQST; + memcpy(msg.MPS_ctrl, mpc->mps_ctrl_addr, ATM_ESA_LEN ); + msg.content.in_info = entry->ctrl_info; + qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); + if (qos != NULL) msg.qos = qos->qos; + msg_to_mpoad( &msg, mpc); + do_gettimeofday(&(entry->reply_wait)); + } + + return CLOSED; } -/* - * If there are no more references to vcc in egress cache, - * we are ready to close it. - */ -static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc) +static void in_cache_put(in_cache_entry *entry) { - if (vcc == NULL) - return; - - dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc:\n"); - if (mpc->eg_ops->search_by_vcc(vcc, mpc) != NULL) - return; /* entry still in use */ - - atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */ - dprintk("mpoa: mpoa_caches.c: close_unused_egress_vcc, closed one:\n"); + if (atomic_dec_and_test(&entry->use)) { + memset(entry, 0, sizeof(in_cache_entry)); + kfree(entry); + } return; } @@ -188,371 +182,395 @@ static void close_unused_egress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc /* * This should be called with write lock on */ -static int in_cache_remove( in_cache_entry *entry, - struct mpoa_client *client ) +static void in_cache_remove_entry(in_cache_entry *entry, + struct mpoa_client *client) { struct atm_vcc *vcc; - struct k_message msg; - unsigned char *ip; - - if(entry == NULL) - return 0; + struct k_message msg; + unsigned char *ip; vcc = entry->shortcut; - ip = (unsigned char *)&entry->ctrl_info.in_dst_ip; - dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]); - - if (entry->prev != NULL) - entry->prev->next = entry->next; - else - client->in_cache = entry->next; - if (entry->next != NULL) - entry->next->prev = entry->prev; - memset(entry, 0, sizeof(in_cache_entry)); - kfree(entry); + ip = (unsigned char *)&entry->ctrl_info.in_dst_ip; + dprintk("mpoa: mpoa_caches.c: removing an ingress entry, ip = %u.%u.%u.%u\n",ip[0], ip[1], ip[2], ip[3]); + + if (entry->prev != NULL) + entry->prev->next = entry->next; + else + client->in_cache = entry->next; + if (entry->next != NULL) + entry->next->prev = entry->prev; + client->in_ops->put(entry); if(client->in_cache == NULL && client->eg_cache == NULL){ - msg.type = STOP_KEEP_ALIVE_SM; + msg.type = STOP_KEEP_ALIVE_SM; msg_to_mpoad(&msg,client); } - close_unused_egress_vcc(vcc, client); - return 1; -} + /* Check if the egress side still uses this VCC */ + if (vcc != NULL) { + eg_cache_entry *eg_entry = client->eg_ops->get_by_vcc(vcc, client); + if (eg_entry != NULL) { + client->eg_ops->put(eg_entry); + return; + } + atm_async_release_vcc(vcc, -EPIPE); + } + return; +} -/* Call this every MPC-p2 seconds... Not exactly correct solution, - but an easy one... */ +/* Call this every MPC-p2 seconds... Not exactly correct solution, + but an easy one... */ static void clear_count_and_expired(struct mpoa_client *client) { - unsigned char *ip; - unsigned long flags; - in_cache_entry *entry, *next_entry; - struct timeval now; + unsigned char *ip; + in_cache_entry *entry, *next_entry; + struct timeval now; do_gettimeofday(&now); - - write_lock_irqsave(&client->ingress_lock, flags); - entry = client->in_cache; - while(entry != NULL){ - entry->count=0; - next_entry = entry->next; - if((now.tv_sec - entry->tv.tv_sec) - > entry->ctrl_info.holding_time){ - ip = (unsigned char*)&entry->ctrl_info.in_dst_ip; - dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); - in_cache_remove(entry, client); - } - entry = next_entry; - } - write_unlock_irqrestore(&client->ingress_lock, flags); - - return; -} -/* Call this every MPC-p4 seconds. */ + write_lock_bh(&client->ingress_lock); + entry = client->in_cache; + while(entry != NULL){ + entry->count=0; + next_entry = entry->next; + if((now.tv_sec - entry->tv.tv_sec) + > entry->ctrl_info.holding_time){ + ip = (unsigned char*)&entry->ctrl_info.in_dst_ip; + dprintk("mpoa: mpoa_caches.c: holding time expired, ip = %u.%u.%u.%u\n", NIPQUAD(ip)); + client->in_ops->remove_entry(entry, client); + } + entry = next_entry; + } + write_unlock_bh(&client->ingress_lock); + + return; +} -static void check_resolving_entries( struct mpoa_client * client ) +/* Call this every MPC-p4 seconds. */ +static void check_resolving_entries(struct mpoa_client *client) { - struct atm_mpoa_qos *qos; - unsigned long flags; - in_cache_entry *entry; - struct timeval now; - struct k_message msg; + struct atm_mpoa_qos *qos; + in_cache_entry *entry; + struct timeval now; + struct k_message msg; do_gettimeofday( &now ); - read_lock_irqsave(&client->ingress_lock, flags); - entry = client->in_cache; - while( entry != NULL ){ - if(entry->entry_state == INGRESS_RESOLVING){ - if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){ - entry = entry->next; /* Entry in hold down */ - continue; - } - if( (now.tv_sec - entry->reply_wait.tv_sec) > - entry->retry_time ){ - entry->retry_time = MPC_C1*( entry->retry_time ); - if(entry->retry_time > client->parameters.mpc_p5){ - /* Retry time maximum exceeded, put entry in hold down. */ - do_gettimeofday(&(entry->hold_down)); - entry->retry_time = client->parameters.mpc_p4; - entry = entry->next; - continue; - } + read_lock_bh(&client->ingress_lock); + entry = client->in_cache; + while( entry != NULL ){ + if(entry->entry_state == INGRESS_RESOLVING){ + if(now.tv_sec - entry->hold_down.tv_sec < client->parameters.mpc_p6){ + entry = entry->next; /* Entry in hold down */ + continue; + } + if( (now.tv_sec - entry->reply_wait.tv_sec) > + entry->retry_time ){ + entry->retry_time = MPC_C1*( entry->retry_time ); + if(entry->retry_time > client->parameters.mpc_p5){ + /* Retry time maximum exceeded, put entry in hold down. */ + do_gettimeofday(&(entry->hold_down)); + entry->retry_time = client->parameters.mpc_p4; + entry = entry->next; + continue; + } /* Ask daemon to send a resolution request. */ - memset(&(entry->hold_down),0,sizeof(struct timeval)); - msg.type = SND_MPOA_RES_RTRY; - memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN); - msg.content.in_info = entry->ctrl_info; - qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); - if (qos != NULL) msg.qos = qos->qos; - msg_to_mpoad(&msg, client); - do_gettimeofday(&(entry->reply_wait)); - } - } - entry = entry->next; - } - read_unlock_irqrestore(&client->ingress_lock, flags); + memset(&(entry->hold_down),0,sizeof(struct timeval)); + msg.type = SND_MPOA_RES_RTRY; + memcpy(msg.MPS_ctrl, client->mps_ctrl_addr, ATM_ESA_LEN); + msg.content.in_info = entry->ctrl_info; + qos = atm_mpoa_search_qos(entry->ctrl_info.in_dst_ip); + if (qos != NULL) msg.qos = qos->qos; + msg_to_mpoad(&msg, client); + do_gettimeofday(&(entry->reply_wait)); + } + } + entry = entry->next; + } + read_unlock_bh(&client->ingress_lock); } /* Call this every MPC-p5 seconds. */ - -static void refresh_entries( struct mpoa_client * client ) +static void refresh_entries(struct mpoa_client *client) { - unsigned long flags; - struct timeval now; - struct in_cache_entry *entry = client->in_cache; - - ddprintk("mpoa: mpoa_caches.c: refresh_entries\n"); + struct timeval now; + struct in_cache_entry *entry = client->in_cache; + + ddprintk("mpoa: mpoa_caches.c: refresh_entries\n"); do_gettimeofday(&now); - read_lock_irqsave(&client->ingress_lock, flags); - while( entry != NULL ){ - if( entry->entry_state == INGRESS_RESOLVED ){ - if(!(entry->refresh_time)) - entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3; + read_lock_bh(&client->ingress_lock); + while( entry != NULL ){ + if( entry->entry_state == INGRESS_RESOLVED ){ + if(!(entry->refresh_time)) + entry->refresh_time = (2*(entry->ctrl_info.holding_time))/3; if( (now.tv_sec - entry->reply_wait.tv_sec) > entry->refresh_time ){ - dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n"); + dprintk("mpoa: mpoa_caches.c: refreshing an entry.\n"); entry->entry_state = INGRESS_REFRESHING; - + } - } - entry = entry->next; - } - read_unlock_irqrestore(&client->ingress_lock, flags); + } + entry = entry->next; + } + read_unlock_bh(&client->ingress_lock); } -static eg_cache_entry *eg_cache_search_by_cache_id(uint32_t cache_id, - struct mpoa_client *client) +static void in_destroy_cache(struct mpoa_client *mpc) { - eg_cache_entry *entry; - unsigned long flags; - - read_lock_irqsave(&client->egress_lock, flags); - entry = client->eg_cache; - while(entry != NULL){ - if( entry->ctrl_info.cache_id == cache_id){ - read_unlock_irqrestore(&client->egress_lock, flags); - return entry; - } - entry = entry->next; - } - read_unlock_irqrestore(&client->egress_lock, flags); - - return NULL; + write_lock_irq(&mpc->ingress_lock); + while(mpc->in_cache != NULL) + mpc->in_ops->remove_entry(mpc->in_cache, mpc); + write_unlock_irq(&mpc->ingress_lock); + + return; } -static eg_cache_entry *eg_cache_search_by_tag(uint32_t tag, - struct mpoa_client *client) +static eg_cache_entry *eg_cache_get_by_cache_id(uint32_t cache_id, struct mpoa_client *mpc) { - unsigned long flags; - eg_cache_entry *entry; - - read_lock_irqsave(&client->egress_lock, flags); - entry = client->eg_cache; - while(entry != NULL){ - if( entry->ctrl_info.tag == tag){ - read_unlock_irqrestore(&client->egress_lock, flags); - return entry; - } - entry = entry->next; - } - read_unlock_irqrestore(&client->egress_lock, flags); - - return NULL; + eg_cache_entry *entry; + + read_lock_irq(&mpc->egress_lock); + entry = mpc->eg_cache; + while(entry != NULL){ + if(entry->ctrl_info.cache_id == cache_id){ + atomic_inc(&entry->use); + read_unlock_irq(&mpc->egress_lock); + return entry; + } + entry = entry->next; + } + read_unlock_irq(&mpc->egress_lock); + + return NULL; } -static eg_cache_entry *eg_cache_search_by_vcc(struct atm_vcc *vcc, - struct mpoa_client *client ) +/* This can be called from any context since it saves CPU flags */ +static eg_cache_entry *eg_cache_get_by_tag(uint32_t tag, struct mpoa_client *mpc) { - unsigned long flags; - eg_cache_entry *entry; - - read_lock_irqsave(&client->egress_lock, flags); - entry = client->eg_cache; - while( entry != NULL ){ - if( entry->shortcut == vcc ) { - read_unlock_irqrestore(&client->egress_lock, flags); - return entry; + unsigned long flags; + eg_cache_entry *entry; + + read_lock_irqsave(&mpc->egress_lock, flags); + entry = mpc->eg_cache; + while (entry != NULL){ + if (entry->ctrl_info.tag == tag) { + atomic_inc(&entry->use); + read_unlock_irqrestore(&mpc->egress_lock, flags); + return entry; } - entry = entry->next; - } - read_unlock_irqrestore(&client->egress_lock, flags); + entry = entry->next; + } + read_unlock_irqrestore(&mpc->egress_lock, flags); - return NULL; + return NULL; } -static eg_cache_entry *eg_cache_search_by_src_ip(uint32_t ipaddr, - struct mpoa_client *client) +/* This can be called from any context since it saves CPU flags */ +static eg_cache_entry *eg_cache_get_by_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc) { - unsigned long flags; - eg_cache_entry *entry; - - read_lock_irqsave(&client->egress_lock, flags); - entry = client->eg_cache; - while( entry != NULL ){ - if(entry->latest_ip_addr == ipaddr) { - break; + unsigned long flags; + eg_cache_entry *entry; + + read_lock_irqsave(&mpc->egress_lock, flags); + entry = mpc->eg_cache; + while (entry != NULL){ + if (entry->shortcut == vcc) { + atomic_inc(&entry->use); + read_unlock_irqrestore(&mpc->egress_lock, flags); + return entry; } - entry = entry->next; - } - read_unlock_irqrestore(&client->egress_lock, flags); + entry = entry->next; + } + read_unlock_irqrestore(&mpc->egress_lock, flags); - return entry; + return NULL; } -/* - * If there are no more references to vcc in ingress cache, - * we are ready to close it. - */ -static void close_unused_ingress_vcc(struct atm_vcc *vcc, struct mpoa_client *mpc) +static eg_cache_entry *eg_cache_get_by_src_ip(uint32_t ipaddr, struct mpoa_client *mpc) { - if (vcc == NULL) - return; + eg_cache_entry *entry; + + read_lock_irq(&mpc->egress_lock); + entry = mpc->eg_cache; + while(entry != NULL){ + if(entry->latest_ip_addr == ipaddr) { + atomic_inc(&entry->use); + read_unlock_irq(&mpc->egress_lock); + return entry; + } + entry = entry->next; + } + read_unlock_irq(&mpc->egress_lock); - dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:\n"); - if (mpc->in_ops->search_by_vcc(vcc, mpc) != NULL) - return; /* entry still in use */ + return NULL; +} - atm_async_release_vcc(vcc, -EPIPE); /* nobody uses this VCC anymore, close it */ - dprintk("mpoa: mpoa_caches.c: close_unused_ingress_vcc:, closed one\n"); +static void eg_cache_put(eg_cache_entry *entry) +{ + if (atomic_dec_and_test(&entry->use)) { + memset(entry, 0, sizeof(eg_cache_entry)); + kfree(entry); + } return; } + /* * This should be called with write lock on */ -static int eg_cache_remove(eg_cache_entry *entry, - struct mpoa_client *client) +static void eg_cache_remove_entry(eg_cache_entry *entry, + struct mpoa_client *client) { struct atm_vcc *vcc; - struct k_message msg; - if(entry == NULL) - return 0; + struct k_message msg; vcc = entry->shortcut; - dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n"); - if (entry->prev != NULL) - entry->prev->next = entry->next; - else - client->eg_cache = entry->next; - if (entry->next != NULL) - entry->next->prev = entry->prev; - memset(entry, 0, sizeof(eg_cache_entry)); - kfree(entry); + dprintk("mpoa: mpoa_caches.c: removing an egress entry.\n"); + if (entry->prev != NULL) + entry->prev->next = entry->next; + else + client->eg_cache = entry->next; + if (entry->next != NULL) + entry->next->prev = entry->prev; + client->eg_ops->put(entry); if(client->in_cache == NULL && client->eg_cache == NULL){ - msg.type = STOP_KEEP_ALIVE_SM; + msg.type = STOP_KEEP_ALIVE_SM; msg_to_mpoad(&msg,client); } - close_unused_ingress_vcc(vcc, client); + /* Check if the ingress side still uses this VCC */ + if (vcc != NULL) { + in_cache_entry *in_entry = client->in_ops->get_by_vcc(vcc, client); + if (in_entry != NULL) { + client->in_ops->put(in_entry); + return; + } + atm_async_release_vcc(vcc, -EPIPE); + } - return 1; -} + return; +} -static eg_cache_entry *new_eg_cache_entry(struct k_message *msg, struct mpoa_client *client) +static eg_cache_entry *eg_cache_add_entry(struct k_message *msg, struct mpoa_client *client) { - unsigned long flags; - unsigned char *ip; - eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL); + unsigned char *ip; + eg_cache_entry *entry = kmalloc(sizeof(eg_cache_entry), GFP_KERNEL); - if (entry == NULL) { - printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n"); - return NULL; + if (entry == NULL) { + printk("mpoa: mpoa_caches.c: new_eg_cache_entry: out of memory\n"); + return NULL; } - ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip; - dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %d.%d.%d.%d, this should be our IP\n", ip[0], ip[1], ip[2], ip[3]); - memset(entry, 0, sizeof(eg_cache_entry)); - - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n"); - write_lock_irqsave(&client->egress_lock, flags); - entry->next = client->eg_cache; - entry->prev = NULL; - if (client->eg_cache != NULL) - client->eg_cache->prev = entry; - client->eg_cache = entry; - write_unlock_irqrestore(&client->egress_lock, flags); - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n"); - - memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN); - entry->ctrl_info = msg->content.eg_info; - do_gettimeofday(&(entry->tv)); - entry->entry_state = EGRESS_RESOLVED; - dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id)); - ip = (unsigned char *)&entry->ctrl_info.mps_ip; - dprintk("mpoa: mpoa_caches.c: mps_ip = %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); - return entry; + ip = (unsigned char *)&msg->content.eg_info.eg_dst_ip; + dprintk("mpoa: mpoa_caches.c: adding an egress entry, ip = %u.%u.%u.%u, this should be our IP\n", NIPQUAD(ip)); + memset(entry, 0, sizeof(eg_cache_entry)); + + atomic_set(&entry->use, 1); + dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: about to lock\n"); + write_lock_irq(&client->egress_lock); + entry->next = client->eg_cache; + entry->prev = NULL; + if (client->eg_cache != NULL) + client->eg_cache->prev = entry; + client->eg_cache = entry; + + memcpy(entry->MPS_ctrl_ATM_addr, client->mps_ctrl_addr, ATM_ESA_LEN); + entry->ctrl_info = msg->content.eg_info; + do_gettimeofday(&(entry->tv)); + entry->entry_state = EGRESS_RESOLVED; + dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry cache_id %lu\n", ntohl(entry->ctrl_info.cache_id)); + ip = (unsigned char *)&entry->ctrl_info.mps_ip; + dprintk("mpoa: mpoa_caches.c: mps_ip = %u.%u.%u.%u\n", NIPQUAD(ip)); + atomic_inc(&entry->use); + + write_unlock_irq(&client->egress_lock); + dprintk("mpoa: mpoa_caches.c: new_eg_cache_entry: unlocked\n"); + + return entry; } static void update_eg_cache_entry(eg_cache_entry * entry, uint16_t holding_time) { - do_gettimeofday(&(entry->tv)); - entry->entry_state = EGRESS_RESOLVED; - entry->ctrl_info.holding_time = holding_time; + do_gettimeofday(&(entry->tv)); + entry->entry_state = EGRESS_RESOLVED; + entry->ctrl_info.holding_time = holding_time; - return; + return; } -static void clear_expired(struct mpoa_client *client){ - eg_cache_entry *entry, *next_entry; - unsigned long flags; - struct timeval now; +static void clear_expired(struct mpoa_client *client) +{ + eg_cache_entry *entry, *next_entry; + struct timeval now; struct k_message msg; - do_gettimeofday(&now); + do_gettimeofday(&now); - write_lock_irqsave(&client->egress_lock, flags); - entry = client->eg_cache; - while(entry != NULL){ - next_entry = entry->next; - if((now.tv_sec - entry->tv.tv_sec) - > entry->ctrl_info.holding_time){ - msg.type = SND_EGRESS_PURGE; + write_lock_irq(&client->egress_lock); + entry = client->eg_cache; + while(entry != NULL){ + next_entry = entry->next; + if((now.tv_sec - entry->tv.tv_sec) + > entry->ctrl_info.holding_time){ + msg.type = SND_EGRESS_PURGE; msg.content.eg_info = entry->ctrl_info; - dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id)); + dprintk("mpoa: mpoa_caches.c: egress_cache: holding time expired, cache_id = %lu.\n",ntohl(entry->ctrl_info.cache_id)); msg_to_mpoad(&msg, client); - eg_cache_remove(entry, client); - } - entry = next_entry; - } - write_unlock_irqrestore(&client->egress_lock, flags); + client->eg_ops->remove_entry(entry, client); + } + entry = next_entry; + } + write_unlock_irq(&client->egress_lock); + + return; +} + +static void eg_destroy_cache(struct mpoa_client *mpc) +{ + write_lock_irq(&mpc->egress_lock); + while(mpc->eg_cache != NULL) + mpc->eg_ops->remove_entry(mpc->eg_cache, mpc); + write_unlock_irq(&mpc->egress_lock); - return; + return; } static struct in_cache_ops ingress_ops = { - new_in_cache_entry, /* new_entry */ - in_cache_search, /* search */ - in_cache_search_with_mask, /* search_with_mask */ - in_cache_search_by_vcc, /* search_by_vcc */ - cache_hit, /* cache_hit */ - in_cache_remove, /* cache_remove */ - clear_count_and_expired, /* clear_count */ - check_resolving_entries, /* check_resolving */ - refresh_entries, /* refresh */ + in_cache_add_entry, /* add_entry */ + in_cache_get, /* get */ + in_cache_get_with_mask, /* get_with_mask */ + in_cache_get_by_vcc, /* get_by_vcc */ + in_cache_put, /* put */ + in_cache_remove_entry, /* remove_entry */ + cache_hit, /* cache_hit */ + clear_count_and_expired, /* clear_count */ + check_resolving_entries, /* check_resolving */ + refresh_entries, /* refresh */ + in_destroy_cache /* destroy_cache */ }; static struct eg_cache_ops egress_ops = { - new_eg_cache_entry, /* new_entry */ - eg_cache_search_by_cache_id, /* search_by_cache_id */ - eg_cache_search_by_tag, /* search_by_tag */ - eg_cache_search_by_vcc, /* search_by_vcc */ - eg_cache_search_by_src_ip, /* search_by_src_ip */ - eg_cache_remove, /* cache_remove */ - update_eg_cache_entry, /* update */ - clear_expired /* clear_expired */ + eg_cache_add_entry, /* add_entry */ + eg_cache_get_by_cache_id, /* get_by_cache_id */ + eg_cache_get_by_tag, /* get_by_tag */ + eg_cache_get_by_vcc, /* get_by_vcc */ + eg_cache_get_by_src_ip, /* get_by_src_ip */ + eg_cache_put, /* put */ + eg_cache_remove_entry, /* remove_entry */ + update_eg_cache_entry, /* update */ + clear_expired, /* clear_expired */ + eg_destroy_cache /* destroy_cache */ }; void atm_mpoa_init_cache(struct mpoa_client *mpc) { - mpc->in_ops = &ingress_ops; - mpc->eg_ops = &egress_ops; + mpc->in_ops = &ingress_ops; + mpc->eg_ops = &egress_ops; - return; + return; } diff --git a/net/atm/mpoa_caches.h b/net/atm/mpoa_caches.h index cdcd6ac16..6c9886a03 100644 --- a/net/atm/mpoa_caches.h +++ b/net/atm/mpoa_caches.h @@ -25,24 +25,27 @@ typedef struct in_cache_entry { struct atm_vcc *shortcut; uint8_t MPS_ctrl_ATM_addr[ATM_ESA_LEN]; struct in_ctrl_info ctrl_info; + atomic_t use; } in_cache_entry; struct in_cache_ops{ - in_cache_entry *(*new_entry)(uint32_t dst_ip, - struct mpoa_client *client); - in_cache_entry *(*search)(uint32_t dst_ip, struct mpoa_client *client); - in_cache_entry *(*search_with_mask)(uint32_t dst_ip, - struct mpoa_client *client, - uint32_t mask); - in_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, - struct mpoa_client *client); - int (*cache_hit)(in_cache_entry *entry, - struct mpoa_client *client); - int (*cache_remove)(in_cache_entry *delEntry, - struct mpoa_client *client ); - void (*clear_count)(struct mpoa_client *client); - void (*check_resolving)(struct mpoa_client *client); - void (*refresh)(struct mpoa_client *client); + in_cache_entry *(*add_entry)(uint32_t dst_ip, + struct mpoa_client *client); + in_cache_entry *(*get)(uint32_t dst_ip, struct mpoa_client *client); + in_cache_entry *(*get_with_mask)(uint32_t dst_ip, + struct mpoa_client *client, + uint32_t mask); + in_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, + struct mpoa_client *client); + void (*put)(in_cache_entry *entry); + void (*remove_entry)(in_cache_entry *delEntry, + struct mpoa_client *client ); + int (*cache_hit)(in_cache_entry *entry, + struct mpoa_client *client); + void (*clear_count)(struct mpoa_client *client); + void (*check_resolving)(struct mpoa_client *client); + void (*refresh)(struct mpoa_client *client); + void (*destroy_cache)(struct mpoa_client *mpc); }; typedef struct eg_cache_entry{ @@ -55,17 +58,20 @@ typedef struct eg_cache_entry{ uint16_t entry_state; uint32_t latest_ip_addr; /* The src IP address of the last packet */ struct eg_ctrl_info ctrl_info; + atomic_t use; } eg_cache_entry; struct eg_cache_ops{ - eg_cache_entry *(*new_entry)(struct k_message *msg, struct mpoa_client *client); - eg_cache_entry *(*search_by_cache_id)(uint32_t cache_id, struct mpoa_client *client); - eg_cache_entry *(*search_by_tag)(uint32_t cache_id, struct mpoa_client *client); - eg_cache_entry *(*search_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client); - eg_cache_entry *(*search_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client); - int (*cache_remove)(eg_cache_entry *entry, struct mpoa_client *client); - void (*update)(eg_cache_entry *entry, uint16_t holding_time); - void (*clear_expired)(struct mpoa_client *client); + eg_cache_entry *(*add_entry)(struct k_message *msg, struct mpoa_client *client); + eg_cache_entry *(*get_by_cache_id)(uint32_t cache_id, struct mpoa_client *client); + eg_cache_entry *(*get_by_tag)(uint32_t cache_id, struct mpoa_client *client); + eg_cache_entry *(*get_by_vcc)(struct atm_vcc *vcc, struct mpoa_client *client); + eg_cache_entry *(*get_by_src_ip)(uint32_t ipaddr, struct mpoa_client *client); + void (*put)(eg_cache_entry *entry); + void (*remove_entry)(eg_cache_entry *entry, struct mpoa_client *client); + void (*update)(eg_cache_entry *entry, uint16_t holding_time); + void (*clear_expired)(struct mpoa_client *client); + void (*destroy_cache)(struct mpoa_client *mpc); }; diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 2493f04aa..fc71c2435 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -78,23 +78,23 @@ static int pvc_getname(struct socket *sock,struct sockaddr *sockaddr, static struct proto_ops SOCKOPS_WRAPPED(pvc_proto_ops) = { - PF_ATMPVC, - atm_release, - pvc_bind, - pvc_connect, - sock_no_socketpair, - sock_no_accept, - pvc_getname, - atm_poll, - atm_ioctl, - sock_no_listen, - pvc_shutdown, - atm_setsockopt, - atm_getsockopt, - sock_no_fcntl, - atm_sendmsg, - atm_recvmsg, - sock_no_mmap + family: PF_ATMPVC, + + release: atm_release, + bind: pvc_bind, + connect: pvc_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: pvc_getname, + poll: atm_poll, + ioctl: atm_ioctl, + listen: sock_no_listen, + shutdown: pvc_shutdown, + setsockopt: atm_setsockopt, + getsockopt: atm_getsockopt, + sendmsg: atm_sendmsg, + recvmsg: atm_recvmsg, + mmap: sock_no_mmap, }; diff --git a/net/atm/raw.c b/net/atm/raw.c index 0899c9f93..738b2a7be 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c @@ -39,7 +39,7 @@ static void atm_pop_raw(struct atm_vcc *vcc,struct sk_buff *skb) DPRINTK("APopR (%d) %d -= %d\n",vcc->vci,vcc->tx_inuse,skb->truesize); atomic_sub(skb->truesize+ATM_PDU_OVHD,&vcc->tx_inuse); dev_kfree_skb_any(skb); - wake_up(&vcc->wsleep); + wake_up(&vcc->sleep); } diff --git a/net/atm/svc.c b/net/atm/svc.c index 47b991557..70fa063cb 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c @@ -397,23 +397,23 @@ static int svc_getsockopt(struct socket *sock,int level,int optname, static struct proto_ops SOCKOPS_WRAPPED(svc_proto_ops) = { - PF_ATMSVC, - svc_release, - svc_bind, - svc_connect, - sock_no_socketpair, - svc_accept, - svc_getname, - atm_poll, - atm_ioctl, - svc_listen, - svc_shutdown, - svc_setsockopt, - svc_getsockopt, - sock_no_fcntl, - atm_sendmsg, - atm_recvmsg, - sock_no_mmap + family: PF_ATMSVC, + + release: svc_release, + bind: svc_bind, + connect: svc_connect, + socketpair: sock_no_socketpair, + accept: svc_accept, + getname: svc_getname, + poll: atm_poll, + ioctl: atm_ioctl, + listen: svc_listen, + shutdown: svc_shutdown, + setsockopt: svc_setsockopt, + getsockopt: svc_getsockopt, + sendmsg: atm_sendmsg, + recvmsg: atm_recvmsg, + mmap: sock_no_mmap, }; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 949c2b3e9..d99065efe 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1795,24 +1795,23 @@ static struct net_proto_family ax25_family_ops = }; static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = { - PF_AX25, - - ax25_release, - ax25_bind, - ax25_connect, - sock_no_socketpair, - ax25_accept, - ax25_getname, - datagram_poll, - ax25_ioctl, - ax25_listen, - ax25_shutdown, - ax25_setsockopt, - ax25_getsockopt, - sock_no_fcntl, - ax25_sendmsg, - ax25_recvmsg, - sock_no_mmap + family: PF_AX25, + + release: ax25_release, + bind: ax25_bind, + connect: ax25_connect, + socketpair: sock_no_socketpair, + accept: ax25_accept, + getname: ax25_getname, + poll: datagram_poll, + ioctl: ax25_ioctl, + listen: ax25_listen, + shutdown: ax25_shutdown, + setsockopt: ax25_setsockopt, + getsockopt: ax25_getsockopt, + sendmsg: ax25_sendmsg, + recvmsg: ax25_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/bridge/br.c b/net/bridge/br.c index 0195f3631..bbbd53a60 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -5,7 +5,7 @@ * Authors: * Lennert Buytenhek <buytenh@gnu.org> * - * $Id: br.c,v 1.41 2000/03/24 01:33:36 davem Exp $ + * $Id: br.c,v 1.42 2000/04/14 10:10:34 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -45,10 +45,8 @@ static int __init br_init(void) br_handle_frame_hook = br_handle_frame; br_ioctl_hook = br_ioctl_deviceless_stub; #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) - write_lock(&lane_bridge_hook_lock); br_fdb_get_hook = br_fdb_get; br_fdb_put_hook = br_fdb_put; - write_unlock(&lane_bridge_hook_lock); #endif register_netdevice_notifier(&br_device_notifier); @@ -71,10 +69,8 @@ static void __exit br_deinit(void) br_call_ioctl_atomic(__br_clear_ioctl_hook); net_call_rx_atomic(__br_clear_frame_hook); #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) - write_lock(&lane_bridge_hook_lock); br_fdb_get_hook = NULL; br_fdb_put_hook = NULL; - write_unlock(&lane_bridge_hook_lock); #endif } diff --git a/net/core/dev.c b/net/core/dev.c index 81a35e7a0..cb6b75d9f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -181,7 +181,7 @@ int netdev_nit=0; * dev_add_pack - add packet handler * @pt: packet type declaration * - * Add a protocol handler to the networking stack. The passed packet_type + * Add a protocol handler to the networking stack. The passed &packet_type * is linked into kernel lists and may not be freed until it has been * removed from the kernel lists. */ @@ -217,7 +217,7 @@ void dev_add_pack(struct packet_type *pt) * @pt: packet type declaration * * Remove a protocol handler that was previously added to the kernel - * protocol handlers by dev_add_pack. The passed packet_type is removed + * protocol handlers by dev_add_pack(). The passed &packet_type is removed * from the kernel lists and can be freed or reused once this function * returns. */ @@ -260,9 +260,9 @@ void dev_remove_pack(struct packet_type *pt) * __dev_get_by_name - find a device by its name * @name: name to find * - * Find an interface by name. Must be called under rtnl semaphore - * or dev_base_lock. If the name is found a pointer to the device - * is returned. If the name is not found then NULL is returned. The + * Find an interface by name. Must be called under RTNL semaphore + * or @dev_base_lock. If the name is found a pointer to the device + * is returned. If the name is not found then %NULL is returned. The * reference counters are not incremented so the caller must be * careful with locks. */ @@ -286,7 +286,7 @@ struct net_device *__dev_get_by_name(const char *name) * Find an interface by name. This can be called from any * context and does its own locking. The returned handle has * the usage count incremented and the caller must use dev_put() to - * release it when it is no longer needed. NULL is returned if no + * release it when it is no longer needed. %NULL is returned if no * matching device is found. */ @@ -336,11 +336,11 @@ int dev_get(const char *name) * __dev_get_by_index - find a device by its ifindex * @ifindex: index of device * - * Search for an interface by index. Returns NULL if the device + * Search for an interface by index. Returns %NULL if the device * is not found or a pointer to the device. The device has not * had its reference counter increased so the caller must be careful - * about locking. The caller must hold either the rtnl semaphore - * or dev_base_lock. + * about locking. The caller must hold either the RTNL semaphore + * or @dev_base_lock. */ struct net_device * __dev_get_by_index(int ifindex) @@ -440,15 +440,15 @@ int dev_alloc_name(struct net_device *dev, const char *name) * @name: name format string * @err: error return pointer * - * Passed a format string - eg "lt%d" it will allocate a network device - * and space for the name. NULL is returned if no memory is available. + * Passed a format string, eg. "lt%d", it will allocate a network device + * and space for the name. %NULL is returned if no memory is available. * If the allocation succeeds then the name is assigned and the - * device pointer returned. NULL is returned if the name allocation failed. - * The cause of an error is returned as a negative errno code in the - * variable err points to. + * device pointer returned. %NULL is returned if the name allocation + * failed. The cause of an error is returned as a negative errno code + * in the variable @err points to. * - * The claler must hold the dev_base or rtnl locks when doing this in order - * to avoid duplicate name allocations. + * The caller must hold the @dev_base or RTNL locks when doing this in + * order to avoid duplicate name allocations. */ struct net_device *dev_alloc(const char *name, int *err) @@ -520,9 +520,9 @@ static int default_rebuild_header(struct sk_buff *skb) * dev_open - prepare an interface for use. * @dev: device to open * - * Takes a device from down to up state. The devices private open + * Takes a device from down to up state. The device's private open * function is invoked and then the multicast lists are loaded. Finally - * the device is moved into the up state and a NETDEV_UP message is + * the device is moved into the up state and a %NETDEV_UP message is * sent to the netdev notifier chain. * * Calling this function on an active interface is a nop. On a failure @@ -622,8 +622,8 @@ void dev_clear_fastroute(struct net_device *dev) * @dev: device to shutdown * * This function moves an active device into down state. A - * NETDEV_GOING_DOWN is sent to the netev notifier chain. The device - * is then deactivated and finally a NETDEV_DOWN is sent to the notifier + * %NETDEV_GOING_DOWN is sent to the netdev notifier chain. The device + * is then deactivated and finally a %NETDEV_DOWN is sent to the notifier * chain. */ @@ -695,9 +695,10 @@ int register_netdevice_notifier(struct notifier_block *nb) * unregister_netdevice_notifier - unregister a network notifier block * @nb: notifier * - * Unregister a notifier previously registered by register_netdevice_notifier - * The notifier is unlinked into the kernel structures and may - * then be reused. A negative errno code is returned on a failure. + * Unregister a notifier previously registered by + * register_netdevice_notifier(). The notifier is unlinked into the + * kernel structures and may then be reused. A negative errno code + * is returned on a failure. */ int unregister_netdevice_notifier(struct notifier_block *nb) @@ -1079,7 +1080,7 @@ static void net_tx_action(struct softirq_action *h) * @fn: function to call * * Make a function call that is atomic with respect to the protocol - * layers + * layers. */ void net_call_rx_atomic(void (*fn)(void)) @@ -1426,10 +1427,11 @@ static int dev_get_info(char *buffer, char **start, off_t offset, int length) static int dev_proc_stats(char *buffer, char **start, off_t offset, int length, int *eof, void *data) { - int i; + int i, lcpu; int len=0; - for (i=0; i<smp_num_cpus; i++) { + for (lcpu=0; lcpu<smp_num_cpus; lcpu++) { + i = cpu_logical_map(lcpu); len += sprintf(buffer+len, "%08x %08x %08x %08x %08x %08x %08x %08x %08x\n", netdev_rx_stat[i].total, netdev_rx_stat[i].dropped, @@ -1554,10 +1556,10 @@ static int dev_get_wireless_info(char * buffer, char **start, off_t offset, * @slave: slave device * @master: new master device * - * Changes the master device of the slave. Pass NULL to break the + * Changes the master device of the slave. Pass %NULL to break the * bonding. The caller must hold the RTNL semaphore. On a failure * a negative errno code is returned. On success the reference counts - * are adjusted, RTM_NEWLINK is sent to the routing socket and the + * are adjusted, %RTM_NEWLINK is sent to the routing socket and the * function returns zero. */ @@ -1629,7 +1631,7 @@ void dev_set_promiscuity(struct net_device *dev, int inc) * Add or remove reception of all multicast frames to a device. While the * count in the device remains above zero the interface remains listening * to all interfaces. Once it hits zero the device reverts back to normal - * filtering operation. A negative inc value is used to drop the counter + * filtering operation. A negative @inc value is used to drop the counter * when releasing a resource needing all multicasts. */ @@ -2005,12 +2007,16 @@ int dev_ioctl(unsigned int cmd, void *arg) return ret; } #ifdef WIRELESS_EXT + /* Take care of Wireless Extensions */ if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) { - dev_load(ifr.ifr_name); - if (IW_IS_SET(cmd)) { - if (!suser()) + /* If command is `set a parameter', or + * `get the encoding parameters', check if + * the user has the right to do it */ + if (IW_IS_SET(cmd) || (cmd == SIOCGIWENCODE)) { + if(!capable(CAP_NET_ADMIN)) return -EPERM; } + dev_load(ifr.ifr_name); rtnl_lock(); ret = dev_ifsioc(&ifr, cmd); rtnl_unlock(); @@ -2051,7 +2057,7 @@ static int dev_boot_phase = 1; * @dev: device to register * * Take a completed network device structure and add it to the kernel - * interfaces. A NETDEV_REGISTER message is sent to the netdev notifier + * interfaces. A %NETDEV_REGISTER message is sent to the netdev notifier * chain. 0 is returned on success. A negative errno code is returned * on a failure to set up the device, or if the name is a duplicate. * diff --git a/net/core/neighbour.c b/net/core/neighbour.c index d97bdc5f2..5a3ccd062 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -54,7 +54,7 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev); static int neigh_glbl_allocs; static struct neigh_table *neigh_tables; -#if defined(__i386__) && defined(__SMP__) +#if defined(__i386__) && defined(CONFIG_SMP) #define ASSERT_WL(n) if ((int)((n)->lock.lock) > 0) { printk("WL assertion failed at " __FILE__ "(%d):" __FUNCTION__ "\n", __LINE__); } #else #define ASSERT_WL(n) do { } while(0) @@ -597,7 +597,7 @@ next_elt: write_unlock(&tbl->lock); } -#ifdef __SMP__ +#ifdef CONFIG_SMP static void neigh_periodic_timer(unsigned long arg) { struct neigh_table *tbl = (struct neigh_table*)arg; @@ -629,7 +629,7 @@ static void neigh_timer_handler(unsigned long arg) state = neigh->nud_state; if (!(state&NUD_IN_TIMER)) { -#ifndef __SMP__ +#ifndef CONFIG_SMP printk("neigh: timer & !nud_in_timer\n"); #endif goto out; @@ -1106,7 +1106,7 @@ void neigh_table_init(struct neigh_table *tbl) 0, SLAB_HWCACHE_ALIGN, NULL, NULL); -#ifdef __SMP__ +#ifdef CONFIG_SMP tasklet_init(&tbl->gc_task, SMP_TIMER_NAME(neigh_periodic_timer), (unsigned long)tbl); #endif init_timer(&tbl->gc_timer); diff --git a/net/core/netfilter.c b/net/core/netfilter.c index 02c3bc989..7f9b9e82b 100644 --- a/net/core/netfilter.c +++ b/net/core/netfilter.c @@ -186,18 +186,10 @@ void nf_dump_skb(int pf, struct sk_buff *skb) dst_port = ntohs(tcp->dest); } - printk("PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu" + printk("PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu" " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", - ip->protocol, - (ntohl(ip->saddr)>>24)&0xFF, - (ntohl(ip->saddr)>>16)&0xFF, - (ntohl(ip->saddr)>>8)&0xFF, - (ntohl(ip->saddr))&0xFF, - src_port, - (ntohl(ip->daddr)>>24)&0xFF, - (ntohl(ip->daddr)>>16)&0xFF, - (ntohl(ip->daddr)>>8)&0xFF, - (ntohl(ip->daddr))&0xFF, + ip->protocol, NIPQUAD(ip->saddr), + src_port, NIPQUAD(ip->daddr), dst_port, ntohs(ip->tot_len), ip->tos, ntohs(ip->id), ntohs(ip->frag_off), ip->ttl); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 54230a273..234e9c182 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4,7 +4,7 @@ * Authors: Alan Cox <iiitac@pyr.swan.ac.uk> * Florian La Roche <rzsfl@rz.uni-sb.de> * - * Version: $Id: skbuff.c,v 1.71 2000/03/29 11:58:33 davem Exp $ + * Version: $Id: skbuff.c,v 1.72 2000/04/13 00:55:54 davem Exp $ * * Fixes: * Alan Cox : Fixed the worst of the load balancer bugs. @@ -83,7 +83,7 @@ static union { * @sz: size * @here: address * - * Out of line support code for skb_put. Not user callable + * Out of line support code for skb_put(). Not user callable. */ void skb_over_panic(struct sk_buff *skb, int sz, void *here) @@ -99,7 +99,7 @@ void skb_over_panic(struct sk_buff *skb, int sz, void *here) * @sz: size * @here: address * - * Out of line support code for skb_push. Not user callable + * Out of line support code for skb_push(). Not user callable. */ @@ -154,12 +154,12 @@ static __inline__ void skb_head_to_pool(struct sk_buff *skb) * @size: size to allocate * @gfp_mask: allocation mask * - * Allocate a new sk_buff. The returned buffer has no headroom and a + * Allocate a new &sk_buff. The returned buffer has no headroom and a * tail room of size bytes. The object has a reference count of one. - * The return is the buffer. On a failure the return is NULL. + * The return is the buffer. On a failure the return is %NULL. * - * Buffers may only be allocated from interrupts using a gfp_mask of - * GFP_ATOMIC. + * Buffers may only be allocated from interrupts using a @gfp_mask of + * %GFP_ATOMIC. */ struct sk_buff *alloc_skb(unsigned int size,int gfp_mask) @@ -300,13 +300,13 @@ void __kfree_skb(struct sk_buff *skb) * @skb: buffer to clone * @gfp_mask: allocation priority * - * Duplicate an sk_buff. The new one is not owned by a socket. Both + * Duplicate an &sk_buff. The new one is not owned by a socket. Both * copies share the same packet data but not structure. The new * buffer has a reference count of 1. If the allocation fails the - * function returns NULL otherwise the new buffer is returned. + * function returns %NULL otherwise the new buffer is returned. * - * If this function is called from an interrupt gfp_mask must be - * GFP_ATOMIC. + * If this function is called from an interrupt gfp_mask() must be + * %GFP_ATOMIC. */ struct sk_buff *skb_clone(struct sk_buff *skb, int gfp_mask) @@ -383,12 +383,12 @@ static void copy_skb_header(struct sk_buff *new, const struct sk_buff *old) * @skb: buffer to copy * @gfp_mask: allocation priority * - * Make a copy of both an sk_buff and its data. This is used when the + * Make a copy of both an &sk_buff and its data. This is used when the * caller wishes to modify the data and needs a private copy of the - * data to alter. Returns NULL on failure or the pointer to the buffer + * data to alter. Returns %NULL on failure or the pointer to the buffer * on success. The returned buffer has a reference count of 1. * - * You must pass GFP_ATOMIC as the allocation priority if this function + * You must pass %GFP_ATOMIC as the allocation priority if this function * is called from an interrupt. */ @@ -423,15 +423,15 @@ struct sk_buff *skb_copy(const struct sk_buff *skb, int gfp_mask) * @newtailroom: new free bytes at tail * @gfp_mask: allocation priority * - * Make a copy of both an sk_buff and its data and while doing so + * Make a copy of both an &sk_buff and its data and while doing so * allocate additional space. * * This is used when the caller wishes to modify the data and needs a * private copy of the data to alter as well as more space for new fields. - * Returns NULL on failure or the pointer to the buffer + * Returns %NULL on failure or the pointer to the buffer * on success. The returned buffer has a reference count of 1. * - * You must pass GFP_ATOMIC as the allocation priority if this function + * You must pass %GFP_ATOMIC as the allocation priority if this function * is called from an interrupt. */ diff --git a/net/core/sock.c b/net/core/sock.c index ce25381c9..4044a7f7d 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -7,7 +7,7 @@ * handler for protocols to use and generic option handler. * * - * Version: $Id: sock.c,v 1.91 2000/03/25 01:55:03 davem Exp $ + * Version: $Id: sock.c,v 1.93 2000/04/13 03:13:29 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -786,18 +786,22 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, if (sk->shutdown&SEND_SHUTDOWN) goto failure; - if (fallback) { - /* The buffer get won't block, or use the atomic queue. - * It does produce annoying no free page messages still. - */ - skb = sock_wmalloc(sk, size, 0, GFP_BUFFER); + if (atomic_read(&sk->wmem_alloc) < sk->sndbuf) { + if (fallback) { + /* The buffer get won't block, or use the atomic queue. + * It does produce annoying no free page messages still. + */ + skb = alloc_skb(size, GFP_BUFFER); + if (skb) + break; + try_size = fallback; + } + skb = alloc_skb(try_size, sk->allocation); if (skb) break; - try_size = fallback; + err = -ENOBUFS; + goto failure; } - skb = sock_wmalloc(sk, try_size, 0, sk->allocation); - if (skb) - break; /* * This means we have too many buffers for this socket already. @@ -813,6 +817,7 @@ struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, timeo = sock_wait_for_wmem(sk, timeo); } + skb_set_owner_w(skb, sk); return skb; interrupted: @@ -1063,7 +1068,7 @@ int sock_no_sendmsg(struct socket *sock, struct msghdr *m, int flags, return -EOPNOTSUPP; } -int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int flags, +int sock_no_recvmsg(struct socket *sock, struct msghdr *m, int len, int flags, struct scm_cookie *scm) { return -EOPNOTSUPP; @@ -1136,7 +1141,6 @@ void sock_init_data(struct socket *sock, struct sock *sk) skb_queue_head_init(&sk->write_queue); skb_queue_head_init(&sk->error_queue); - spin_lock_init(&sk->timer_lock); init_timer(&sk->timer); sk->allocation = GFP_KERNEL; diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index c560ea01e..ab244350e 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c @@ -2032,24 +2032,23 @@ static struct net_proto_family dn_family_ops = { }; static struct proto_ops dn_proto_ops = { - AF_DECnet, - - dn_release, - dn_bind, - dn_connect, - sock_no_socketpair, - dn_accept, - dn_getname, - dn_poll, - dn_ioctl, - dn_listen, - dn_shutdown, - dn_setsockopt, - dn_getsockopt, - sock_no_fcntl, - dn_sendmsg, - dn_recvmsg, - sock_no_mmap + family: AF_DECnet, + + release: dn_release, + bind: dn_bind, + connect: dn_connect, + socketpair: sock_no_socketpair, + accept: dn_accept, + getname: dn_getname, + poll: dn_poll, + ioctl: dn_ioctl, + listen: dn_listen, + shutdown: dn_shutdown, + setsockopt: dn_setsockopt, + getsockopt: dn_getsockopt, + sendmsg: dn_sendmsg, + recvmsg: dn_recvmsg, + mmap: sock_no_mmap, }; #ifdef CONFIG_SYSCTL @@ -2091,7 +2090,7 @@ static int __init decnet_setup(char *str) decnet_address = dn_htons(area << 10 | node); dn_dn2eth(decnet_ether_address, dn_ntohs(decnet_address)); - return 0; + return 1; } __setup("decnet=", decnet_setup); diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c index ff65e9ae6..c1931c867 100644 --- a/net/decnet/sysctl_net_decnet.c +++ b/net/decnet/sysctl_net_decnet.c @@ -54,6 +54,22 @@ static struct ctl_table_header *dn_table_header = NULL; #define ISALPHA(x) (ISLOWER(x) || ISUPPER(x)) #define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x)) +static void strip_it(char *str) +{ + for(;;) { + switch(*str) { + case ' ': + case '\n': + case '\r': + case ':': + *str = 0; + case 0: + return; + } + str++; + } +} + /* * Simple routine to parse an ascii DECnet address * into a network order address. @@ -159,8 +175,9 @@ static int dn_node_address_handler(ctl_table *table, int write, return -EFAULT; addr[len] = 0; + strip_it(addr); - if (parse_addr(&dnaddr, buffer)) + if (parse_addr(&dnaddr, addr)) return -EINVAL; dn_dev_devices_off(); @@ -257,8 +274,6 @@ static int dn_def_dev_handler(ctl_table *table, int write, } if (write) { - int i; - if (*lenp > 16) return -E2BIG; @@ -266,9 +281,7 @@ static int dn_def_dev_handler(ctl_table *table, int write, return -EFAULT; devname[*lenp] = 0; - for(i = 0; i < (*lenp); i++) - if (devname[i] == '\n') - devname[i] = 0; + strip_it(devname); if ((dev = __dev_get_by_name(devname)) == NULL) return -ENODEV; diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index a22098207..79ae4d3ca 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -705,24 +705,23 @@ static struct net_proto_family econet_family_ops = { }; static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { - PF_ECONET, - - econet_release, - econet_bind, - sock_no_connect, - sock_no_socketpair, - sock_no_accept, - econet_getname, - datagram_poll, - econet_ioctl, - sock_no_listen, - sock_no_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - econet_sendmsg, - econet_recvmsg, - sock_no_mmap + family: PF_ECONET, + + release: econet_release, + bind: econet_bind, + connect: sock_no_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: econet_getname, + poll: datagram_poll, + ioctl: econet_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: econet_sendmsg, + recvmsg: econet_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> @@ -1131,7 +1130,7 @@ void __exit econet_proto_exit(void) #endif } -int __init econet_proto_init(struct net_proto *pro) +int __init econet_proto_init(void) { extern void econet_sysctl_register(void); sock_register(&econet_family_ops); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index d3fc0e38f..40aa7cd3a 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -5,7 +5,7 @@ * * PF_INET protocol family socket handler. * - * Version: $Id: af_inet.c,v 1.109 2000/03/25 01:55:10 davem Exp $ + * Version: $Id: af_inet.c,v 1.110 2000/04/25 04:13:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -893,45 +893,43 @@ static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } struct proto_ops inet_stream_ops = { - PF_INET, - - inet_release, - inet_bind, - inet_stream_connect, - sock_no_socketpair, - inet_accept, - inet_getname, - tcp_poll, - inet_ioctl, - inet_listen, - inet_shutdown, - inet_setsockopt, - inet_getsockopt, - sock_no_fcntl, - inet_sendmsg, - inet_recvmsg, - sock_no_mmap + family: PF_INET, + + release: inet_release, + bind: inet_bind, + connect: inet_stream_connect, + socketpair: sock_no_socketpair, + accept: inet_accept, + getname: inet_getname, + poll: tcp_poll, + ioctl: inet_ioctl, + listen: inet_listen, + shutdown: inet_shutdown, + setsockopt: inet_setsockopt, + getsockopt: inet_getsockopt, + sendmsg: inet_sendmsg, + recvmsg: inet_recvmsg, + mmap: sock_no_mmap }; struct proto_ops inet_dgram_ops = { - PF_INET, - - inet_release, - inet_bind, - inet_dgram_connect, - sock_no_socketpair, - sock_no_accept, - inet_getname, - datagram_poll, - inet_ioctl, - sock_no_listen, - inet_shutdown, - inet_setsockopt, - inet_getsockopt, - sock_no_fcntl, - inet_sendmsg, - inet_recvmsg, - sock_no_mmap + family: PF_INET, + + release: inet_release, + bind: inet_bind, + connect: inet_dgram_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: inet_getname, + poll: datagram_poll, + ioctl: inet_ioctl, + listen: sock_no_listen, + shutdown: inet_shutdown, + setsockopt: inet_setsockopt, + getsockopt: inet_getsockopt, + sendmsg: inet_sendmsg, + recvmsg: inet_recvmsg, + mmap: sock_no_mmap, }; struct net_proto_family inet_family_ops = { diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 588cdf030..9def6b16b 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1,6 +1,6 @@ /* linux/net/inet/arp.c * - * Version: $Id: arp.c,v 1.84 2000/01/18 08:24:14 davem Exp $ + * Version: $Id: arp.c,v 1.86 2000/04/26 09:36:36 davem Exp $ * * Copyright (C) 1994 by Florian La Roche * @@ -1021,7 +1021,6 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) char hbuffer[HBUFFERLEN]; int i,j,k; const char hexbuf[] = "0123456789ABCDEF"; - char abuf[16]; size = sprintf(buffer,"IP address HW type Flags HW address Mask Device\n"); @@ -1060,15 +1059,21 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) } #endif - size = sprintf(buffer+len, - "%-17s0x%-10x0x%-10x%s", - in_ntoa2(*(u32*)n->primary_key, abuf), - hatype, - arp_state_to_flags(n), - hbuffer); - size += sprintf(buffer+len+size, - " %-17s %s\n", - "*", dev->name); + { + char tbuf[16]; + sprintf(tbuf, "%u.%u.%u.%u", NIPQUAD(*(u32*)n->primary_key)); + + size = sprintf(buffer+len, "%-16s 0x%-10x0x%-10x%s", + tbuf, + hatype, + arp_state_to_flags(n), + hbuffer); + + size += sprintf(buffer+len+size, + " %-8s %s\n", + "*", dev->name); + } + read_unlock(&n->lock); len += size; @@ -1091,8 +1096,8 @@ static int arp_get_info(char *buffer, char **start, off_t offset, int length) int hatype = dev ? dev->type : 0; size = sprintf(buffer+len, - "%-17s0x%-10x0x%-10x%s", - in_ntoa2(*(u32*)n->key, abuf), + "%u.%u.%u.%u0x%-10x0x%-10x%s", + NIPQUAD(*(u32*)n->key), hatype, ATF_PUBL|ATF_PERM, "00:00:00:00:00:00"); diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 5ee1bfd78..03095f1a2 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c @@ -5,7 +5,7 @@ * * IPv4 Forwarding Information Base: policy rules. * - * Version: $Id: fib_rules.c,v 1.14 1999/08/31 07:03:29 davem Exp $ + * Version: $Id: fib_rules.c,v 1.15 2000/04/15 01:48:10 davem Exp $ * * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> * @@ -298,7 +298,8 @@ int fib_lookup(const struct rt_key *key, struct fib_result *res) u32 daddr = key->dst; u32 saddr = key->src; -FRprintk("Lookup: %08x <- %08x ", key->dst, key->src); +FRprintk("Lookup: %u.%u.%u.%u <- %u.%u.%u.%u ", + NIPQUAD(key->dst), NIPQUAD(key->src)); read_lock(&fib_rules_lock); for (r = fib_rules; r; r=r->r_next) { if (((saddr^r->r_src) & r->r_srcmask) || diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 7c462ac08..f15d94388 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -3,7 +3,7 @@ * * Alan Cox, <alan@redhat.com> * - * Version: $Id: icmp.c,v 1.67 2000/03/25 01:55:11 davem Exp $ + * Version: $Id: icmp.c,v 1.69 2000/04/15 01:48:10 davem Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -521,9 +521,12 @@ void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) } if (ip_route_output(&rt, daddr, rt->rt_spec_dst, RT_TOS(skb->nh.iph->tos), 0)) goto out; - ip_build_xmit(sk, icmp_glue_bits, icmp_param, - icmp_param->data_len+sizeof(struct icmphdr), - &ipc, rt, MSG_DONTWAIT); + if (icmpv4_xrlim_allow(rt, icmp_param->icmph.type, + icmp_param->icmph.code)) { + ip_build_xmit(sk, icmp_glue_bits, icmp_param, + icmp_param->data_len+sizeof(struct icmphdr), + &ipc, rt, MSG_DONTWAIT); + } ip_rt_put(rt); out: icmp_xmit_unlock_bh(); @@ -720,7 +723,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len) case ICMP_FRAG_NEEDED: if (ipv4_config.no_pmtu_disc) { if (net_ratelimit()) - printk(KERN_INFO "ICMP: %d.%d.%d.%d: fragmentation needed and DF set.\n", + printk(KERN_INFO "ICMP: %u.%u.%u.%u: fragmentation needed and DF set.\n", NIPQUAD(iph->daddr)); } else { unsigned short new_mtu; @@ -732,7 +735,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len) break; case ICMP_SR_FAILED: if (net_ratelimit()) - printk(KERN_INFO "ICMP: %d.%d.%d.%d: Source Route Failed.\n", NIPQUAD(iph->daddr)); + printk(KERN_INFO "ICMP: %u.%u.%u.%u: Source Route Failed.\n", NIPQUAD(iph->daddr)); break; default: break; @@ -762,7 +765,7 @@ static void icmp_unreach(struct icmphdr *icmph, struct sk_buff *skb, int len) if (inet_addr_type(iph->daddr) == RTN_BROADCAST) { if (net_ratelimit()) - printk(KERN_WARNING "%d.%d.%d.%d sent an invalid ICMP error to a broadcast.\n", + printk(KERN_WARNING "%u.%u.%u.%u sent an invalid ICMP error to a broadcast.\n", NIPQUAD(skb->nh.iph->saddr)); return; } @@ -983,9 +986,8 @@ static void icmp_address_reply(struct icmphdr *icmph, struct sk_buff *skb, int l break; } if (!ifa && net_ratelimit()) { - char b1[16], b2[16]; - printk(KERN_INFO "Wrong address mask %s from %s/%s\n", - in_ntoa2(mask, b1), in_ntoa2(rt->rt_src, b2), dev->name); + printk(KERN_INFO "Wrong address mask %u.%u.%u.%u from %s/%u.%u.%u.%u\n", + NIPQUAD(mask), dev->name, NIPQUAD(rt->rt_src)); } } read_unlock(&in_dev->lock); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 852a4fb2c..70f8cfb90 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -5,7 +5,7 @@ * * The IP fragmentation functionality. * - * Version: $Id: ip_fragment.c,v 1.47 2000/02/09 21:11:33 davem Exp $ + * Version: $Id: ip_fragment.c,v 1.49 2000/04/15 01:48:10 davem Exp $ * * Authors: Fred N. van Kempen <waltje@uWalt.NL.Mugnet.ORG> * Alan Cox <Alan.Cox@linux.org> @@ -387,9 +387,14 @@ static struct sk_buff *ip_glue(struct ipq *qp) */ skb->security = qp->fragments->skb->security; +#ifdef CONFIG_NETFILTER + /* Connection association is same as fragment (if any). */ + skb->nfct = qp->fragments->skb->nfct; + nf_conntrack_get(skb->nfct); #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = qp->fragments->skb->nf_debug; #endif +#endif /* Done with all fragments. Fixup the new IP header. */ iph = skb->nh.iph; @@ -594,7 +599,7 @@ out: */ out_oversize: if (net_ratelimit()) - printk(KERN_INFO "Oversized packet received from %d.%d.%d.%d\n", + printk(KERN_INFO "Oversized packet received from %u.%u.%u.%u\n", NIPQUAD(iph->saddr)); /* the skb isn't in a fragment, so fall through to free it */ out_freeskb: diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 0c755dbcd..700bb24f7 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -5,7 +5,7 @@ * * The Internet Protocol (IP) module. * - * Version: $Id: ip_input.c,v 1.46 2000/02/22 23:54:26 davem Exp $ + * Version: $Id: ip_input.c,v 1.48 2000/04/15 01:48:10 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -162,7 +162,13 @@ int ip_call_ra_chain(struct sk_buff *skb) read_lock(&ip_ra_lock); for (ra = ip_ra_chain; ra; ra = ra->next) { struct sock *sk = ra->sk; - if (sk && sk->num == protocol) { + + /* If socket is bound to an interface, only report + * the packet if it came from that interface. + */ + if (sk && sk->num == protocol + && ((sk->bound_dev_if == 0) + || (sk->bound_dev_if == skb->dev->ifindex))) { if (skb->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { skb = ip_defrag(skb); if (skb == NULL) { @@ -349,7 +355,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb) if (in_dev) { if (!IN_DEV_SOURCE_ROUTE(in_dev)) { if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) - printk(KERN_INFO "source route option %d.%d.%d.%d -> %d.%d.%d.%d\n", + printk(KERN_INFO "source route option %u.%u.%u.%u -> %u.%u.%u.%u\n", NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); in_dev_put(in_dev); goto drop; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 454e81fea..cd51bcef3 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -1,5 +1,5 @@ /* - * $Id: ipconfig.c,v 1.27 2000/02/21 15:51:41 davem Exp $ + * $Id: ipconfig.c,v 1.30 2000/04/15 01:48:10 davem Exp $ * * Automatic Configuration of IP -- use BOOTP or RARP or user-supplied * information to configure own IP address and routes. @@ -77,7 +77,7 @@ u8 root_server_path[256] __initdata = { 0, }; /* Path to mount as root */ #define CONFIG_IP_PNP_DYNAMIC -static int ic_proto_enabled __initdata = 0 /* Protocols enabled */ +int ic_proto_enabled __initdata = 0 /* Protocols enabled */ #ifdef CONFIG_IP_PNP_BOOTP | IC_BOOTP #endif @@ -227,17 +227,20 @@ static int __init ic_setup_if(void) strcpy(ir.ifr_ifrn.ifrn_name, ic_dev->name); set_sockaddr(sin, ic_myaddr, 0); if ((err = ic_dev_ioctl(SIOCSIFADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface address (%d).\n", err); + printk(KERN_ERR "IP-Config: Unable to set interface address (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } set_sockaddr(sin, ic_netmask, 0); if ((err = ic_dev_ioctl(SIOCSIFNETMASK, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface netmask (%d).\n", err); + printk(KERN_ERR "IP-Config: Unable to set interface netmask (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } set_sockaddr(sin, ic_myaddr | ~ic_netmask, 0); if ((err = ic_dev_ioctl(SIOCSIFBRDADDR, &ir)) < 0) { - printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%d).\n", err); + printk(KERN_ERR "IP-Config: Unable to set interface broadcast address (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } return 0; @@ -261,7 +264,8 @@ static int __init ic_setup_routes(void) set_sockaddr((struct sockaddr_in *) &rm.rt_gateway, ic_gateway, 0); rm.rt_flags = RTF_UP | RTF_GATEWAY; if ((err = ic_route_ioctl(SIOCADDRT, &rm)) < 0) { - printk(KERN_ERR "IP-Config: Cannot add default route (%d).\n", err); + printk(KERN_ERR "IP-Config: Cannot add default route (%u.%u.%u.%u).\n", + NIPQUAD(err)); return -1; } } @@ -294,10 +298,11 @@ static int __init ic_defaults(void) else if (IN_CLASSC(ntohl(ic_myaddr))) ic_netmask = htonl(IN_CLASSC_NET); else { - printk(KERN_ERR "IP-Config: Unable to guess netmask for address %08x\n", ic_myaddr); + printk(KERN_ERR "IP-Config: Unable to guess netmask for address %u.%u.%u.%u\n", + NIPQUAD(ic_myaddr)); return -1; } - printk("IP-Config: Guessing netmask %s\n", in_ntoa(ic_netmask)); + printk("IP-Config: Guessing netmask %u.%u.%u.%u\n", NIPQUAD(ic_netmask)); } return 0; @@ -807,10 +812,10 @@ static int __init ic_dynamic(void) if (!ic_got_reply) return -1; - printk("IP-Config: Got %s answer from %s, ", + printk("IP-Config: Got %s answer from %u.%u.%u.%u, ", (ic_got_reply & IC_BOOTP) ? "BOOTP" : "RARP", - in_ntoa(ic_servaddr)); - printk("my address is %s\n", in_ntoa(ic_myaddr)); + NIPQUAD(ic_servaddr)); + printk("my address is %u.%u.%u.%u\n", NIPQUAD(ic_myaddr)); return 0; } @@ -986,7 +991,7 @@ static int __init ip_auto_config_setup(char *addrs) num++; } - return 0; + return 1; } static int __init nfsaddrs_config_setup(char *addrs) diff --git a/net/ipv4/netfilter/ip_conntrack_core.c b/net/ipv4/netfilter/ip_conntrack_core.c index 197c2e3b4..fdfd747e2 100644 --- a/net/ipv4/netfilter/ip_conntrack_core.c +++ b/net/ipv4/netfilter/ip_conntrack_core.c @@ -343,6 +343,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, size_t hash, repl_hash; struct ip_conntrack_expect *expected; enum ip_conntrack_info ctinfo; + unsigned long extra_jiffies; int i; if (!invert_tuple(&repl_tuple, tuple, protocol)) { @@ -366,19 +367,24 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, repl_hash = hash_conntrack(&repl_tuple); memset(conntrack, 0, sizeof(struct ip_conntrack)); - atomic_set(&conntrack->ct_general.use, 1); + atomic_set(&conntrack->ct_general.use, 2); conntrack->ct_general.destroy = destroy_conntrack; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple; conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack; conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple; conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack; - for(i=0; i < IP_CT_NUMBER; i++) + for (i=0; i < IP_CT_NUMBER; i++) conntrack->infos[i].master = &conntrack->ct_general; - if (!protocol->new(conntrack, skb->nh.iph, skb->len)) { + extra_jiffies = protocol->new(conntrack, skb->nh.iph, skb->len); + if (!extra_jiffies) { kmem_cache_free(ip_conntrack_cachep, conntrack); return 1; } + conntrack->timeout.data = (unsigned long)conntrack; + conntrack->timeout.function = death_by_timeout; + conntrack->timeout.expires = jiffies + extra_jiffies; + add_timer(&conntrack->timeout); /* Sew in at head of hash list. */ WRITE_LOCK(&ip_conntrack_lock); @@ -421,7 +427,7 @@ init_conntrack(const struct ip_conntrack_tuple *tuple, } static void -resolve_normal_ct(struct sk_buff *skb) +resolve_normal_ct(struct sk_buff *skb, int create) { struct ip_conntrack_tuple tuple; struct ip_conntrack_tuple_hash *h; @@ -436,7 +442,7 @@ resolve_normal_ct(struct sk_buff *skb) do { /* look for tuple match */ h = ip_conntrack_find_get(&tuple, NULL); - if (!h && init_conntrack(&tuple, proto, skb)) + if (!h && (!create || init_conntrack(&tuple, proto, skb))) return; } while (!h); @@ -464,13 +470,15 @@ resolve_normal_ct(struct sk_buff *skb) } /* Return conntrack and conntrack_info a given skb */ -struct ip_conntrack * -ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) +static struct ip_conntrack * +__ip_conntrack_get(struct sk_buff *skb, + enum ip_conntrack_info *ctinfo, + int create) { if (!skb->nfct) { /* It may be an icmp error... */ if (!icmp_error_track(skb)) - resolve_normal_ct(skb); + resolve_normal_ct(skb, create); } if (skb->nfct) { @@ -485,6 +493,12 @@ ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) return NULL; } +struct ip_conntrack * +ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo) +{ + return __ip_conntrack_get(skb, ctinfo, 0); +} + /* Netfilter hook itself. */ unsigned int ip_conntrack_in(unsigned int hooknum, struct sk_buff **pskb, @@ -512,13 +526,13 @@ unsigned int ip_conntrack_in(unsigned int hooknum, return NF_STOLEN; } - ct = ip_conntrack_get(*pskb, &ctinfo); - if (!ct) + ct = __ip_conntrack_get(*pskb, &ctinfo, 1); + if (!ct) { /* Not valid part of a connection */ return NF_ACCEPT; + } proto = find_proto((*pskb)->nh.iph->protocol); - /* If this is new, this is first time timer will be set */ ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo); if (ret == -1) { @@ -645,24 +659,16 @@ void ip_conntrack_helper_unregister(struct ip_conntrack_helper *me) MOD_DEC_USE_COUNT; } -/* Refresh conntrack for this many jiffies: if noone calls this, - conntrack will vanish with current skb. */ +/* Refresh conntrack for this many jiffies. */ void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies) { + IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct); + WRITE_LOCK(&ip_conntrack_lock); - /* If this hasn't had a timer before, it's still being set up */ - if (ct->timeout.data == 0) { - ct->timeout.data = (unsigned long)ct; - ct->timeout.function = death_by_timeout; + /* Need del_timer for race avoidance (may already be dying). */ + if (del_timer(&ct->timeout)) { ct->timeout.expires = jiffies + extra_jiffies; - atomic_inc(&ct->ct_general.use); add_timer(&ct->timeout); - } else { - /* Need del_timer for race avoidance (may already be dying). */ - if (del_timer(&ct->timeout)) { - ct->timeout.expires = jiffies + extra_jiffies; - add_timer(&ct->timeout); - } } WRITE_UNLOCK(&ip_conntrack_lock); } diff --git a/net/ipv4/netfilter/ip_conntrack_proto_generic.c b/net/ipv4/netfilter/ip_conntrack_proto_generic.c index 77a491e34..6e2bcbcec 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_generic.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_generic.c @@ -48,9 +48,10 @@ static int established(struct ip_conntrack *conntrack, } /* Called when a new connection for this protocol found. */ -static int new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len) +static unsigned long +new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len) { - return 1; + return GENERIC_TIMEOUT; } struct ip_conntrack_protocol ip_conntrack_generic_protocol diff --git a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c index cbbc1ab8c..17e126119 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_icmp.c @@ -86,8 +86,8 @@ static int icmp_packet(struct ip_conntrack *ct, } /* Called when a new connection for this protocol found. */ -static int icmp_new(struct ip_conntrack *conntrack, - struct iphdr *iph, size_t len) +static unsigned long icmp_new(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len) { static u_int8_t valid_new[] = { [ICMP_ECHO] = 1, @@ -103,7 +103,7 @@ static int icmp_new(struct ip_conntrack *conntrack, DUMP_TUPLE(&conntrack->tuplehash[0].tuple); return 0; } - return 1; + return ICMP_TIMEOUT; } struct ip_conntrack_protocol ip_conntrack_protocol_icmp diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index 893248943..997a917bc 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -189,14 +189,13 @@ static int tcp_packet(struct ip_conntrack *conntrack, conntrack->proto.tcp_state = newconntrack; WRITE_UNLOCK(&tcp_lock); - /* Refresh: need write lock to write to conntrack. */ ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]); return NF_ACCEPT; } /* Called when a new connection for this protocol found. */ -static int tcp_new(struct ip_conntrack *conntrack, - struct iphdr *iph, size_t len) +static unsigned long tcp_new(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len) { enum tcp_conntrack newconntrack; struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl); @@ -210,11 +209,10 @@ static int tcp_new(struct ip_conntrack *conntrack, if (newconntrack == TCP_CONNTRACK_MAX) { DEBUGP("ip_conntrack_tcp: invalid new deleting.\n"); return 0; - } else { - conntrack->proto.tcp_state = newconntrack; - ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]); } - return 1; + + conntrack->proto.tcp_state = newconntrack; + return tcp_timeouts[conntrack->proto.tcp_state]; } struct ip_conntrack_protocol ip_conntrack_protocol_tcp diff --git a/net/ipv4/netfilter/ip_conntrack_proto_udp.c b/net/ipv4/netfilter/ip_conntrack_proto_udp.c index 79ec82151..521bd7654 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_udp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_udp.c @@ -54,10 +54,10 @@ static int udp_packet(struct ip_conntrack *conntrack, } /* Called when a new connection for this protocol found. */ -static int udp_new(struct ip_conntrack *conntrack, - struct iphdr *iph, size_t len) +static unsigned long udp_new(struct ip_conntrack *conntrack, + struct iphdr *iph, size_t len) { - return 1; + return UDP_TIMEOUT; } struct ip_conntrack_protocol ip_conntrack_protocol_udp diff --git a/net/ipv4/netfilter/ip_conntrack_standalone.c b/net/ipv4/netfilter/ip_conntrack_standalone.c index 9030d9d41..3219f4c85 100644 --- a/net/ipv4/netfilter/ip_conntrack_standalone.c +++ b/net/ipv4/netfilter/ip_conntrack_standalone.c @@ -169,8 +169,6 @@ static unsigned int ip_refrag(unsigned int hooknum, interface. We degfragment them at LOCAL_OUT, however, so we have to refragment them here. */ if ((*pskb)->len > rt->u.dst.pmtu) { - DEBUGP("ip_conntrack: refragm %p (size %u) to %u (okfn %p)\n", - *pskb, (*pskb)->len, rt->u.dst.pmtu, okfn); /* No hook can be after us, so this should be OK. */ ip_fragment(*pskb, okfn); return NF_STOLEN; @@ -178,13 +176,29 @@ static unsigned int ip_refrag(unsigned int hooknum, return NF_ACCEPT; } +static unsigned int ip_conntrack_local(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) { + if (net_ratelimit()) + printk("ipt_hook: happy cracking.\n"); + return NF_ACCEPT; + } + return ip_conntrack_in(hooknum, pskb, in, out, okfn); +} + /* Connection tracking may drop packets, but never alters them, so make it the first hook. */ static struct nf_hook_ops ip_conntrack_in_ops = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING, NF_IP_PRI_CONNTRACK }; static struct nf_hook_ops ip_conntrack_local_out_ops -= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_LOCAL_OUT, += { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_CONNTRACK }; /* Refragmenter; last chance. */ static struct nf_hook_ops ip_conntrack_out_ops diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index bfcc435c2..0c582b867 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -130,6 +130,11 @@ ip_nat_out(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) + return NF_ACCEPT; + /* We can hit fragment here; forwarded packets get defragmented by connection tracking coming in, then fragmented (grr) by the forward code. @@ -150,6 +155,21 @@ ip_nat_out(unsigned int hooknum, return ip_nat_fn(hooknum, pskb, in, out, okfn); } +static unsigned int +ip_nat_local_fn(unsigned int hooknum, + struct sk_buff **pskb, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ + /* root is playing with raw sockets. */ + if ((*pskb)->len < sizeof(struct iphdr) + || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) + return NF_ACCEPT; + + return ip_nat_fn(hooknum, pskb, in, out, okfn); +} + /* We must be after connection tracking and before packet filtering. */ /* Before packet filtering, change destination */ @@ -160,7 +180,7 @@ static struct nf_hook_ops ip_nat_out_ops = { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC}; /* Before packet filtering, change destination */ static struct nf_hook_ops ip_nat_local_out_ops -= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST }; += { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST }; /* Protocol registration. */ int ip_nat_protocol_register(struct ip_nat_protocol *proto) diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 80e43d977..72b47568b 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -509,7 +509,7 @@ static int ipq_get_info(char *buffer, char **start, off_t offset, int length) "Peer pid : %d\n" "Peer died : %d\n" "Peer copy mode : %d\n" - "Peer copy range : %d\n" + "Peer copy range : %Zu\n" "Queue length : %d\n" "Queue max. length : %d\n" "Queue flushing : %d\n" diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 66f47c386..73424cef8 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -39,7 +39,7 @@ #define IP_NF_ASSERT(x) \ do { \ if (!(x)) \ - printk("IPT_ASSERT: %s:%s:%u\n", \ + printk("IP_NF_ASSERT: %s:%s:%u\n", \ __FUNCTION__, __FILE__, __LINE__); \ } while(0) #else @@ -683,7 +683,6 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, target = find_target_lock(t->u.name, &ret, &ipt_mutex); if (!target) { duprintf("check_entry: `%s' not found\n", t->u.name); - up(&ipt_mutex); return ret; } if (target->me) @@ -1283,17 +1282,16 @@ ipt_register_target(struct ipt_target *target) { int ret; + MOD_INC_USE_COUNT; ret = down_interruptible(&ipt_mutex); if (ret != 0) return ret; - if (list_named_insert(&ipt_target, target)) { - MOD_INC_USE_COUNT; - ret = 0; - } else { + if (!list_named_insert(&ipt_target, target)) { duprintf("ipt_register_target: `%s' already in list!\n", target->name); ret = -EINVAL; + MOD_DEC_USE_COUNT; } up(&ipt_mutex); return ret; @@ -1313,16 +1311,18 @@ ipt_register_match(struct ipt_match *match) { int ret; + MOD_INC_USE_COUNT; ret = down_interruptible(&ipt_mutex); - if (ret != 0) + if (ret != 0) { + MOD_DEC_USE_COUNT; return ret; - + } if (list_named_insert(&ipt_match, match)) { - MOD_INC_USE_COUNT; ret = 0; } else { duprintf("ipt_register_match: `%s' already in list!\n", match->name); + MOD_DEC_USE_COUNT; ret = -EINVAL; } up(&ipt_mutex); @@ -1346,10 +1346,12 @@ int ipt_register_table(struct ipt_table *table) static struct ipt_table_info bootstrap = { 0, 0, { 0 }, { 0 }, { }, { } }; + MOD_INC_USE_COUNT; newinfo = vmalloc(sizeof(struct ipt_table_info) + SMP_ALIGN(table->table->size) * smp_num_cpus); if (!newinfo) { ret = -ENOMEM; + MOD_DEC_USE_COUNT; return ret; } memcpy(newinfo->entries, table->table->entries, table->table->size); @@ -1361,12 +1363,14 @@ int ipt_register_table(struct ipt_table *table) table->table->underflow); if (ret != 0) { vfree(newinfo); + MOD_DEC_USE_COUNT; return ret; } ret = down_interruptible(&ipt_mutex); if (ret != 0) { vfree(newinfo); + MOD_DEC_USE_COUNT; return ret; } @@ -1386,7 +1390,6 @@ int ipt_register_table(struct ipt_table *table) table->lock = RW_LOCK_UNLOCKED; list_prepend(&ipt_tables, table); - MOD_INC_USE_COUNT; unlock: up(&ipt_mutex); @@ -1394,6 +1397,7 @@ int ipt_register_table(struct ipt_table *table) free_unlock: vfree(newinfo); + MOD_DEC_USE_COUNT; goto unlock; } diff --git a/net/ipv4/netfilter/ipchains_core.c b/net/ipv4/netfilter/ipchains_core.c index 419b0382c..e22898512 100644 --- a/net/ipv4/netfilter/ipchains_core.c +++ b/net/ipv4/netfilter/ipchains_core.c @@ -419,18 +419,10 @@ static void dump_packet(const struct iphdr *ip, printk("%d ",f->ipfw.fw_redirpt); } - printk("%s PROTO=%d %d.%d.%d.%d:%hu %d.%d.%d.%d:%hu" + printk("%s PROTO=%d %u.%u.%u.%u:%hu %u.%u.%u.%u:%hu" " L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", - ifname, ip->protocol, - (ntohl(ip->saddr)>>24)&0xFF, - (ntohl(ip->saddr)>>16)&0xFF, - (ntohl(ip->saddr)>>8)&0xFF, - (ntohl(ip->saddr))&0xFF, - src_port, - (ntohl(ip->daddr)>>24)&0xFF, - (ntohl(ip->daddr)>>16)&0xFF, - (ntohl(ip->daddr)>>8)&0xFF, - (ntohl(ip->daddr))&0xFF, + ifname, ip->protocol, NIPQUAD(ip->saddr), + src_port, NIPQUAD(ip->daddr), dst_port, ntohs(ip->tot_len), ip->tos, ntohs(ip->id), ntohs(ip->frag_off), ip->ttl); diff --git a/net/ipv4/netfilter/ipfwadm_core.c b/net/ipv4/netfilter/ipfwadm_core.c index a1f4e16cf..904e7c824 100644 --- a/net/ipv4/netfilter/ipfwadm_core.c +++ b/net/ipv4/netfilter/ipfwadm_core.c @@ -17,7 +17,7 @@ * license in recognition of the original copyright. * -- Alan Cox. * - * $Id: ipfwadm_core.c,v 1.1 2000/03/17 14:42:00 davem Exp $ + * $Id: ipfwadm_core.c,v 1.2 2000/04/15 01:48:10 davem Exp $ * * Ported from BSD to Linux, * Alan Cox 22/Nov/1994. @@ -143,10 +143,7 @@ #define dprintf4(a1,a2,a3,a4) #endif -#define print_ip(a) printk("%d.%d.%d.%d",(ntohl(a)>>24)&0xFF,\ - (ntohl(a)>>16)&0xFF,\ - (ntohl(a)>>8)&0xFF,\ - (ntohl(a))&0xFF); +#define print_ip(a) printk("%u.%u.%u.%u", NIPQUAD(a)); #ifdef DEBUG_IP_FIREWALL #define dprint_ip(a) print_ip(a) diff --git a/net/ipv4/netfilter/ipt_LOG.c b/net/ipv4/netfilter/ipt_LOG.c index 4675a94b8..395b1b301 100644 --- a/net/ipv4/netfilter/ipt_LOG.c +++ b/net/ipv4/netfilter/ipt_LOG.c @@ -38,14 +38,7 @@ static void dump_packet(const struct ipt_log_info *info, * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ printk("SRC=%u.%u.%u.%u DST=%u.%u.%u.%u ", - (ntohl(iph->saddr)>>24)&0xFF, - (ntohl(iph->saddr)>>16)&0xFF, - (ntohl(iph->saddr)>>8)&0xFF, - (ntohl(iph->saddr))&0xFF, - (ntohl(iph->daddr)>>24)&0xFF, - (ntohl(iph->daddr)>>16)&0xFF, - (ntohl(iph->daddr)>>8)&0xFF, - (ntohl(iph->daddr))&0xFF); + NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ printk("LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", @@ -210,11 +203,7 @@ static void dump_packet(const struct ipt_log_info *info, break; case ICMP_REDIRECT: /* Max length: 24 "GATEWAY=255.255.255.255 " */ - printk("GATEWAY=%u.%u.%u.%u ", - (ntohl(icmph->un.gateway)>>24)&0xFF, - (ntohl(icmph->un.gateway)>>16)&0xFF, - (ntohl(icmph->un.gateway)>>8)&0xFF, - (ntohl(icmph->un.gateway))&0xFF); + printk("GATEWAY=%u.%u.%u.%u ", NIPQUAD(icmph->un.gateway)); /* Fall through */ case ICMP_DEST_UNREACH: case ICMP_SOURCE_QUENCH: diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index d6a7c57f5..4d94a4cc0 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -7,7 +7,7 @@ * PROC file system. It is mainly used for debugging and * statistics. * - * Version: $Id: proc.c,v 1.41 2000/01/21 23:45:57 davem Exp $ + * Version: $Id: proc.c,v 1.42 2000/04/16 01:11:37 davem Exp $ * * Authors: Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> * Gerald J. Heim, <heim@peanuts.informatik.uni-tuebingen.de> @@ -56,7 +56,7 @@ static int fold_prot_inuse(struct proto *proto) int cpu; for (cpu=0; cpu<smp_num_cpus; cpu++) - res += proto->stats[cpu].inuse; + res += proto->stats[cpu_logical_map(cpu)].inuse; return res; } @@ -99,8 +99,10 @@ static unsigned long fold_field(unsigned long *begin, int sz, int nr) sz /= sizeof(unsigned long); - for (i=0; i<2*smp_num_cpus; i++) - res += begin[i*sz + nr]; + for (i=0; i<smp_num_cpus; i++) { + res += begin[2*cpu_logical_map(i)*sz + nr]; + res += begin[(2*cpu_logical_map(i)+1)*sz + nr]; + } return res; } diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index e9aa1952a..a7555b6b5 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -5,7 +5,7 @@ * * RAW - implementation of IP "raw" sockets. * - * Version: $Id: raw.c,v 1.48 2000/01/18 08:24:15 davem Exp $ + * Version: $Id: raw.c,v 1.49 2000/04/25 04:13:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -644,26 +644,20 @@ out: } struct proto raw_prot = { - raw_close, /* close */ - udp_connect, /* connect */ - udp_disconnect, /* disconnect */ - NULL, /* accept */ + name: "RAW", + close: raw_close, + connect: udp_connect, + disconnect: udp_disconnect, #ifdef CONFIG_IP_MROUTE - ipmr_ioctl, /* ioctl */ -#else - NULL, /* ioctl */ + ioctl: ipmr_ioctl, #endif - raw_init, /* init */ - NULL, /* destroy */ - NULL, /* shutdown */ - raw_setsockopt, /* setsockopt */ - raw_getsockopt, /* getsockopt */ - raw_sendmsg, /* sendmsg */ - raw_recvmsg, /* recvmsg */ - raw_bind, /* bind */ - raw_rcv_skb, /* backlog_rcv */ - raw_v4_hash, /* hash */ - raw_v4_unhash, /* unhash */ - NULL, /* get_port */ - "RAW", /* name */ + init: raw_init, + setsockopt: raw_setsockopt, + getsockopt: raw_getsockopt, + sendmsg: raw_sendmsg, + recvmsg: raw_recvmsg, + bind: raw_bind, + backlog_rcv: raw_rcv_skb, + hash: raw_v4_hash, + unhash: raw_v4_unhash, }; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index afab828fb..ec254e313 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -5,7 +5,7 @@ * * ROUTE - implementation of the IP router. * - * Version: $Id: route.c,v 1.83 2000/03/23 05:34:13 davem Exp $ + * Version: $Id: route.c,v 1.86 2000/04/24 07:03:14 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -616,9 +616,9 @@ restart: #if RT_CACHE_DEBUG >= 2 if (rt->u.rt_next) { struct rtable * trt; - printk("rt_cache @%02x: %08x", hash, rt->rt_dst); + printk("rt_cache @%02x: %u.%u.%u.%u", hash, NIPQUAD(rt->rt_dst)); for (trt=rt->u.rt_next; trt; trt=trt->u.rt_next) - printk(" . %08x", trt->rt_dst); + printk(" . %u.%u.%u.%u", NIPQUAD(trt->rt_dst)); printk("\n"); } #endif @@ -816,10 +816,10 @@ void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw, reject_redirect: #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) - printk(KERN_INFO "Redirect from %X/%s to %X ignored." - "Path = %X -> %X, tos %02x\n", - ntohl(old_gw), dev->name, ntohl(new_gw), - ntohl(saddr), ntohl(daddr), tos); + printk(KERN_INFO "Redirect from %u.%u.%u.%u on %s about %u.%u.%u.%u ignored.\n" + " Advised path = %u.%u.%u.%u -> %u.%u.%u.%u, tos %02x\n", + NIPQUAD(old_gw), dev->name, NIPQUAD(new_gw), + NIPQUAD(saddr), NIPQUAD(daddr), tos); #endif in_dev_put(in_dev); } @@ -836,7 +836,8 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) if ((rt->rt_flags&RTCF_REDIRECTED) || rt->u.dst.expires) { unsigned hash = rt_hash_code(rt->key.dst, rt->key.src^(rt->key.oif<<5), rt->key.tos); #if RT_CACHE_DEBUG >= 1 - printk(KERN_DEBUG "ip_rt_advice: redirect to %d.%d.%d.%d/%02x dropped\n", NIPQUAD(rt->rt_dst), rt->key.tos); + printk(KERN_DEBUG "ip_rt_advice: redirect to %u.%u.%u.%u/%02x dropped\n", + NIPQUAD(rt->rt_dst), rt->key.tos); #endif rt_del(hash, rt); return NULL; @@ -896,8 +897,10 @@ void ip_rt_send_redirect(struct sk_buff *skb) #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && rt->u.dst.rate_tokens == ip_rt_redirect_number && net_ratelimit()) - printk(KERN_WARNING "host %08x/if%d ignores redirects for %08x to %08x.\n", - rt->rt_src, rt->rt_iif, rt->rt_dst, rt->rt_gateway); + printk(KERN_WARNING "host %u.%u.%u.%u/if%d ignores redirects for " + "%u.%u.%u.%u to %u.%u.%u.%u.\n", + NIPQUAD(rt->rt_src), rt->rt_iif, + NIPQUAD(rt->rt_dst), NIPQUAD(rt->rt_gateway)); #endif } out: @@ -1061,8 +1064,9 @@ static void ipv4_link_failure(struct sk_buff *skb) static int ip_rt_bug(struct sk_buff *skb) { - printk(KERN_DEBUG "ip_rt_bug: %08x -> %08x, %s\n", skb->nh.iph->saddr, - skb->nh.iph->daddr, skb->dev ? skb->dev->name : "?"); + printk(KERN_DEBUG "ip_rt_bug: %u.%u.%u.%u -> %u.%u.%u.%u, %s\n", + NIPQUAD(skb->nh.iph->saddr), NIPQUAD(skb->nh.iph->daddr), + skb->dev ? skb->dev->name : "?"); kfree_skb(skb); return 0; } @@ -1499,7 +1503,8 @@ no_route: martian_destination: #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) - printk(KERN_WARNING "martian destination %08x from %08x, dev %s\n", daddr, saddr, dev->name); + printk(KERN_WARNING "martian destination %u.%u.%u.%u from %u.%u.%u.%u, dev %s\n", + NIPQUAD(daddr), NIPQUAD(saddr), dev->name); #endif e_inval: err = -EINVAL; @@ -1513,16 +1518,20 @@ martian_source: #ifdef CONFIG_IP_ROUTE_VERBOSE if (IN_DEV_LOG_MARTIANS(in_dev) && net_ratelimit()) { /* - * RFC1812 recommenadtion, if source is martian, + * RFC1812 recommendation, if source is martian, * the only hint is MAC header. */ - printk(KERN_WARNING "martian source %08x for %08x, dev %s\n", saddr, daddr, dev->name); + printk(KERN_WARNING "martian source %u.%u.%u.%u from %u.%u.%u.%u, on dev %s\n", + NIPQUAD(daddr), NIPQUAD(saddr), dev->name); if (dev->hard_header_len) { int i; unsigned char *p = skb->mac.raw; - printk(KERN_WARNING "ll header:"); - for (i=0; i<dev->hard_header_len; i++, p++) - printk(" %02x", *p); + printk(KERN_WARNING "ll header: "); + for (i=0; i<dev->hard_header_len; i++, p++) { + printk("%02x", *p); + if(i<(dev->hard_header_len-1)) + printk(":"); + } printk("\n"); } } @@ -2218,15 +2227,20 @@ static int ip_rt_acct_read(char *buffer, char **start, off_t offset, memcpy(dst, src, length); -#ifdef __SMP__ - if (smp_num_cpus > 1) { +#ifdef CONFIG_SMP + if (smp_num_cpus > 1 || cpu_logical_map(0) != 0) { int i; int cnt = length/4; - for (i=1; i<smp_num_cpus; i++) { + for (i=0; i<smp_num_cpus; i++) { + int cpu = cpu_logical_map(i); int k; - src += (256/4)*sizeof(struct ip_rt_acct); + if (cpu == 0) + continue; + + src = (u32*)(((u8*)ip_rt_acct) + offset + + cpu*256*sizeof(struct ip_rt_acct)); for (k=0; k<cnt; k++) dst[k] += src[k]; @@ -2245,7 +2259,7 @@ void __init ip_rt_init(void) #ifdef CONFIG_NET_CLS_ROUTE for (order=0; - (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*smp_num_cpus; order++) + (PAGE_SIZE<<order) < 256*sizeof(ip_rt_acct)*NR_CPUS; order++) /* NOTHING */; ip_rt_acct = (struct ip_rt_acct *)__get_free_pages(GFP_KERNEL, order); if (!ip_rt_acct) diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 098d91ba1..c4343b707 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp.c,v 1.166 2000/03/25 01:55:11 davem Exp $ + * Version: $Id: tcp.c,v 1.169 2000/04/20 14:41:16 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -583,9 +583,13 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) answ = 0; else if (sk->urginline || !tp->urg_data || before(tp->urg_seq,tp->copied_seq) || - !before(tp->urg_seq,tp->rcv_nxt)) + !before(tp->urg_seq,tp->rcv_nxt)) { answ = tp->rcv_nxt - tp->copied_seq; - else + + /* Subtract 1, if FIN is in queue. */ + if (answ && !skb_queue_empty(&sk->receive_queue)) + answ -= ((struct sk_buff*)sk->receive_queue.prev)->h.th->fin; + } else answ = tp->urg_seq - tp->copied_seq; release_sock(sk); break; @@ -618,7 +622,7 @@ int tcp_listen_start(struct sock *sk) sk->max_ack_backlog = 0; sk->ack_backlog = 0; - tp->accept_queue = NULL; + tp->accept_queue = tp->accept_queue_tail = NULL; tp->syn_wait_lock = RW_LOCK_UNLOCKED; lopt = kmalloc(sizeof(struct tcp_listen_opt), GFP_KERNEL); @@ -677,7 +681,7 @@ static void tcp_listen_stop (struct sock *sk) write_lock_bh(&tp->syn_wait_lock); tp->listen_opt =NULL; write_unlock_bh(&tp->syn_wait_lock); - tp->accept_queue = NULL; + tp->accept_queue = tp->accept_queue_tail = NULL; if (lopt->qlen) { for (i=0; i<TCP_SYNQ_HSIZE; i++) { @@ -951,10 +955,14 @@ int tcp_sendmsg(struct sock *sk, struct msghdr *msg, int size) tmp += copy; queue_it = 0; } - skb = sock_wmalloc(sk, tmp, 0, GFP_KERNEL); - /* If we didn't get any memory, we need to sleep. */ - if (skb == NULL) { + if (tcp_memory_free(sk)) { + skb = alloc_skb(tmp, GFP_KERNEL); + if (skb == NULL) + goto do_oom; + skb_set_owner_w(skb, sk); + } else { + /* If we didn't get any memory, we need to sleep. */ set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags); set_bit(SOCK_NOSPACE, &sk->socket->flags); @@ -1029,6 +1037,9 @@ do_shutdown: err = -EPIPE; } goto out; +do_oom: + err = copied ? : -ENOBUFS; + goto out; do_interrupted: if(copied) err = copied; @@ -2027,7 +2038,8 @@ struct sock *tcp_accept(struct sock *sk, int flags, int *err) } req = tp->accept_queue; - tp->accept_queue = req->dl_next; + if ((tp->accept_queue = req->dl_next) == NULL) + tp->accept_queue_tail = NULL; newsk = req->sk; tcp_acceptq_removed(sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 3ba12bc52..f062cb2fb 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.191 2000/03/25 01:55:13 davem Exp $ + * Version: $Id: tcp_input.c,v 1.193 2000/04/20 14:41:16 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1618,6 +1618,7 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) tp->fin_seq = TCP_SKB_CB(skb)->end_seq; tp->ack.pending = 1; + tp->ack.quick = 0; sk->shutdown |= RCV_SHUTDOWN; @@ -1670,9 +1671,9 @@ static void tcp_fin(struct sk_buff *skb, struct sock *sk, struct tcphdr *th) /* Do not send POLL_HUP for half duplex close. */ if (sk->shutdown == SHUTDOWN_MASK || sk->state == TCP_CLOSE) - sock_wake_async(sk->socket, 1, POLL_HUP); + sk_wake_async(sk, 1, POLL_HUP); else - sock_wake_async(sk->socket, 1, POLL_IN); + sk_wake_async(sk, 1, POLL_IN); } } @@ -2207,7 +2208,7 @@ static void tcp_check_urg(struct sock * sk, struct tcphdr * th) kill_proc(sk->proc, SIGURG, 1); else kill_pg(-sk->proc, SIGURG, 1); - sock_wake_async(sk->socket, 3, POLL_PRI); + sk_wake_async(sk, 3, POLL_PRI); } /* We may be adding urgent data when the last byte read was @@ -2783,7 +2784,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct open_request *req, newtp->fin_seq = req->rcv_isn; newtp->urg_data = 0; newtp->listen_opt = NULL; - newtp->accept_queue = NULL; + newtp->accept_queue = newtp->accept_queue_tail = NULL; /* Deinitialize syn_wait_lock to trap illegal accesses. */ memset(&newtp->syn_wait_lock, 0, sizeof(newtp->syn_wait_lock)); @@ -3162,7 +3163,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, if(!sk->dead) { sk->state_change(sk); - sock_wake_async(sk->socket, 0, POLL_OUT); + sk_wake_async(sk, 0, POLL_OUT); } if (tp->write_pending) { @@ -3444,7 +3445,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, */ if (!sk->dead) { sk->state_change(sk); - sock_wake_async(sk->socket,0,POLL_OUT); + sk_wake_async(sk,0,POLL_OUT); } tp->snd_una = TCP_SKB_CB(skb)->ack_seq; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c9f4e82b..5facec2c8 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.205 2000/03/26 09:16:08 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.207 2000/04/25 04:13:34 davem Exp $ * * IPv4 specific functions * @@ -1384,7 +1384,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) peer->v4daddr == saddr) { if (xtime.tv_sec < peer->tcp_ts_stamp + TCP_PAWS_MSL && (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW) { - NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %08x/%u\n", peer->tcp_ts, req->ts_recent, saddr, ntohs(skb->h.th->source))); + NETDEBUG(printk(KERN_DEBUG "TW_REC: reject openreq %u/%u %u.%u.%u.%u/%u\n", \ + peer->tcp_ts, req->ts_recent, NIPQUAD(saddr), ntohs(skb->h.th->source))); NET_INC_STATS_BH(PAWSPassiveRejected); dst_release(dst); goto drop_and_free; @@ -1402,7 +1403,9 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) * to destinations, already remembered * to the moment of synflood. */ - NETDEBUG(if (net_ratelimit()) printk(KERN_DEBUG "TCP: drop open request from %08x/%u\n", saddr, ntohs(skb->h.th->source))); + NETDEBUG(if (net_ratelimit()) \ + printk(KERN_DEBUG "TCP: drop open request from %u.%u.%u.%u/%u\n", \ + NIPQUAD(saddr), ntohs(skb->h.th->source))); TCP_INC_STATS_BH(TcpAttemptFails); dst_release(dst); goto drop_and_free; @@ -2169,24 +2172,23 @@ out_no_bh: } struct proto tcp_prot = { - tcp_close, /* close */ - tcp_v4_connect, /* connect */ - tcp_disconnect, /* disconnect */ - tcp_accept, /* accept */ - tcp_ioctl, /* ioctl */ - tcp_v4_init_sock, /* init */ - tcp_v4_destroy_sock, /* destroy */ - tcp_shutdown, /* shutdown */ - tcp_setsockopt, /* setsockopt */ - tcp_getsockopt, /* getsockopt */ - tcp_sendmsg, /* sendmsg */ - tcp_recvmsg, /* recvmsg */ - NULL, /* bind */ - tcp_v4_do_rcv, /* backlog_rcv */ - tcp_v4_hash, /* hash */ - tcp_unhash, /* unhash */ - tcp_v4_get_port, /* get_port */ - "TCP", /* name */ + name: "TCP", + close: tcp_close, + connect: tcp_v4_connect, + disconnect: tcp_disconnect, + accept: tcp_accept, + ioctl: tcp_ioctl, + init: tcp_v4_init_sock, + destroy: tcp_v4_destroy_sock, + shutdown: tcp_shutdown, + setsockopt: tcp_setsockopt, + getsockopt: tcp_getsockopt, + sendmsg: tcp_sendmsg, + recvmsg: tcp_recvmsg, + backlog_rcv: tcp_v4_do_rcv, + hash: tcp_v4_hash, + unhash: tcp_unhash, + get_port: tcp_v4_get_port, }; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 600140764..0fdb6b3f8 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_output.c,v 1.123 2000/03/25 01:52:05 davem Exp $ + * Version: $Id: tcp_output.c,v 1.124 2000/04/08 07:21:24 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1121,27 +1121,22 @@ void tcp_send_delayed_ack(struct sock *sk) timeout = jiffies + ato; /* Use new timeout only if there wasn't a older one earlier. */ - spin_lock_bh(&sk->timer_lock); - if (!tp->delack_timer.prev || !del_timer(&tp->delack_timer)) { - sock_hold(sk); - tp->delack_timer.expires = timeout; - } else { + if (timer_pending(&tp->delack_timer)) { + unsigned long old_timeout = tp->delack_timer.expires; + /* If delack timer was blocked or is about to expire, * send ACK now. */ - if (tp->ack.blocked || time_before_eq(tp->delack_timer.expires, jiffies+(ato>>2))) { - spin_unlock_bh(&sk->timer_lock); - + if (tp->ack.blocked || time_before_eq(old_timeout, jiffies+(ato>>2))) { tcp_send_ack(sk); - __sock_put(sk); return; } - if (time_before(timeout, tp->delack_timer.expires)) - tp->delack_timer.expires = timeout; + if (!time_before(timeout, old_timeout)) + timeout = old_timeout; } - add_timer(&tp->delack_timer); - spin_unlock_bh(&sk->timer_lock); + if (!mod_timer(&tp->delack_timer, timeout)) + sock_hold(sk); #ifdef TCP_FORMAL_WINDOW /* Explanation. Header prediction path does not handle diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6b3695c3e..9e9887707 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.74 2000/02/14 20:56:30 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.75 2000/04/08 07:21:25 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -49,8 +49,6 @@ void tcp_init_xmit_timers(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - spin_lock_init(&sk->timer_lock); - init_timer(&tp->retransmit_timer); tp->retransmit_timer.function=&tcp_retransmit_timer; tp->retransmit_timer.data = (unsigned long) sk; @@ -76,7 +74,6 @@ void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - spin_lock_bh(&sk->timer_lock); switch (what) { case TCP_TIME_RETRANS: /* When seting the transmit timer the probe timer @@ -84,50 +81,44 @@ void tcp_reset_xmit_timer(struct sock *sk, int what, unsigned long when) * The delayed ack timer can be set if we are changing the * retransmit timer when removing acked frames. */ - if(tp->probe_timer.prev && del_timer(&tp->probe_timer)) + if (timer_pending(&tp->probe_timer) && del_timer(&tp->probe_timer)) __sock_put(sk); - if (!tp->retransmit_timer.prev || !del_timer(&tp->retransmit_timer)) - sock_hold(sk); if (when > TCP_RTO_MAX) { printk(KERN_DEBUG "reset_xmit_timer sk=%p when=0x%lx, caller=%p\n", sk, when, NET_CALLER(sk)); when = TCP_RTO_MAX; } - mod_timer(&tp->retransmit_timer, jiffies+when); + if (!mod_timer(&tp->retransmit_timer, jiffies+when)) + sock_hold(sk); break; case TCP_TIME_DACK: - if (!tp->delack_timer.prev || !del_timer(&tp->delack_timer)) + if (!mod_timer(&tp->delack_timer, jiffies+when)) sock_hold(sk); - mod_timer(&tp->delack_timer, jiffies+when); break; case TCP_TIME_PROBE0: - if (!tp->probe_timer.prev || !del_timer(&tp->probe_timer)) + if (!mod_timer(&tp->probe_timer, jiffies+when)) sock_hold(sk); - mod_timer(&tp->probe_timer, jiffies+when); - break; + break; default: printk(KERN_DEBUG "bug: unknown timer value\n"); }; - spin_unlock_bh(&sk->timer_lock); } void tcp_clear_xmit_timers(struct sock *sk) { struct tcp_opt *tp = &sk->tp_pinfo.af_tcp; - spin_lock_bh(&sk->timer_lock); - if(tp->retransmit_timer.prev && del_timer(&tp->retransmit_timer)) + if(timer_pending(&tp->retransmit_timer) && del_timer(&tp->retransmit_timer)) __sock_put(sk); - if(tp->delack_timer.prev && del_timer(&tp->delack_timer)) + if(timer_pending(&tp->delack_timer) && del_timer(&tp->delack_timer)) __sock_put(sk); tp->ack.blocked = 0; - if(tp->probe_timer.prev && del_timer(&tp->probe_timer)) + if(timer_pending(&tp->probe_timer) && del_timer(&tp->probe_timer)) __sock_put(sk); - if(sk->timer.prev && del_timer(&sk->timer)) + if(timer_pending(&sk->timer) && del_timer(&sk->timer)) __sock_put(sk); - spin_unlock_bh(&sk->timer_lock); } static void tcp_write_err(struct sock *sk) @@ -138,6 +129,35 @@ static void tcp_write_err(struct sock *sk) tcp_done(sk); } +/* Do not allow orphaned sockets to eat all our resources. + * This is direct violation of TCP specs, but it is required + * to prevent DoS attacks. It is called when a retransmission timeout + * or zero probe timeout occurs on orphaned socket. + * + * Criterium is still not confirmed experimentally and may change. + * We kill the socket, if: + * 1. If number of orphaned sockets exceeds an administratively configured + * limit. + * 2. Under pessimistic assumption that all the orphans eat memory not + * less than this one, total consumed memory exceeds all + * the available memory. + */ +static int tcp_out_of_resources(struct sock *sk, int do_reset) +{ + int orphans = atomic_read(&tcp_orphan_count); + + if (orphans >= sysctl_tcp_max_orphans || + ((orphans*atomic_read(&sk->wmem_alloc))>>PAGE_SHIFT) >= num_physpages) { + if (net_ratelimit()) + printk(KERN_INFO "Out of socket memory\n"); + if (do_reset) + tcp_send_active_reset(sk, GFP_ATOMIC); + tcp_done(sk); + return 1; + } + return 0; +} + /* A write timeout has occurred. Process the after effects. */ static int tcp_write_timeout(struct sock *sk) { @@ -172,9 +192,14 @@ static int tcp_write_timeout(struct sock *sk) dst_negative_advice(&sk->dst_cache); } + retry_until = sysctl_tcp_retries2; - if (sk->dead) + if (sk->dead) { + if (tcp_out_of_resources(sk, tp->retransmits < retry_until)) + return 1; + retry_until = sysctl_tcp_orphan_retries; + } } if (tp->retransmits >= retry_until) { @@ -257,7 +282,14 @@ static void tcp_probe_timer(unsigned long data) * with RFCs, only probe timer combines both retransmission timeout * and probe timeout in one bottle. --ANK */ - max_probes = sk->dead ? sysctl_tcp_orphan_retries : sysctl_tcp_retries2; + max_probes = sysctl_tcp_retries2; + + if (sk->dead) { + if (tcp_out_of_resources(sk, tp->probes_out <= max_probes)) + goto out_unlock; + + max_probes = sysctl_tcp_orphan_retries; + } if (tp->probes_out > max_probes) { tcp_write_err(sk); @@ -574,6 +606,8 @@ static void tcp_retransmit_timer(unsigned long data) tp->retransmits++; tp->rto = min(tp->rto << 1, TCP_RTO_MAX); tcp_reset_xmit_timer(sk, TCP_TIME_RETRANS, tp->rto); + if (tp->retransmits > sysctl_tcp_retries1) + __sk_dst_reset(sk); TCP_CHECK_TIMER(sk); out_unlock: @@ -676,19 +710,14 @@ static void tcp_synack_timer(struct sock *sk) void tcp_delete_keepalive_timer (struct sock *sk) { - spin_lock_bh(&sk->timer_lock); - if (sk->timer.prev && del_timer (&sk->timer)) + if (timer_pending(&sk->timer) && del_timer (&sk->timer)) __sock_put(sk); - spin_unlock_bh(&sk->timer_lock); } void tcp_reset_keepalive_timer (struct sock *sk, unsigned long len) { - spin_lock_bh(&sk->timer_lock); - if(!sk->timer.prev || !del_timer(&sk->timer)) + if (!mod_timer(&sk->timer, jiffies+len)) sock_hold(sk); - mod_timer(&sk->timer, jiffies+len); - spin_unlock_bh(&sk->timer_lock); } void tcp_set_keepalive(struct sock *sk, int val) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e188b4997..570e1de2b 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -5,7 +5,7 @@ * * The User Datagram Protocol (UDP). * - * Version: $Id: udp.c,v 1.80 2000/02/27 19:51:43 davem Exp $ + * Version: $Id: udp.c,v 1.81 2000/04/25 04:13:34 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1041,22 +1041,17 @@ out: } struct proto udp_prot = { - udp_close, /* close */ - udp_connect, /* connect */ - udp_disconnect, /* disconnect */ - NULL, /* accept */ - udp_ioctl, /* ioctl */ - NULL, /* init */ - NULL, /* destroy */ - NULL, /* shutdown */ - ip_setsockopt, /* setsockopt */ - ip_getsockopt, /* getsockopt */ - udp_sendmsg, /* sendmsg */ - udp_recvmsg, /* recvmsg */ - NULL, /* bind */ - udp_queue_rcv_skb, /* backlog_rcv */ - udp_v4_hash, /* hash */ - udp_v4_unhash, /* unhash */ - udp_v4_get_port, /* good_socknum */ - "UDP", /* name */ + name: "UDP", + close: udp_close, + connect: udp_connect, + disconnect: udp_disconnect, + ioctl: udp_ioctl, + setsockopt: ip_setsockopt, + getsockopt: ip_getsockopt, + sendmsg: udp_sendmsg, + recvmsg: udp_recvmsg, + backlog_rcv: udp_queue_rcv_skb, + hash: udp_v4_hash, + unhash: udp_v4_unhash, + get_port: udp_v4_get_port, }; diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 919abf4f9..8b039a658 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/af_inet.c * - * $Id: af_inet6.c,v 1.55 2000/02/27 19:51:47 davem Exp $ + * $Id: af_inet6.c,v 1.56 2000/04/25 04:13:34 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -445,45 +445,43 @@ static int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) } struct proto_ops inet6_stream_ops = { - PF_INET6, - - inet6_release, - inet6_bind, - inet_stream_connect, /* ok */ - sock_no_socketpair, /* a do nothing */ - inet_accept, /* ok */ - inet6_getname, - tcp_poll, /* ok */ - inet6_ioctl, /* must change */ - inet_listen, /* ok */ - inet_shutdown, /* ok */ - inet_setsockopt, /* ok */ - inet_getsockopt, /* ok */ - sock_no_fcntl, /* ok */ - inet_sendmsg, /* ok */ - inet_recvmsg, /* ok */ - sock_no_mmap + family: PF_INET6, + + release: inet6_release, + bind: inet6_bind, + connect: inet_stream_connect, /* ok */ + socketpair: sock_no_socketpair, /* a do nothing */ + accept: inet_accept, /* ok */ + getname: inet6_getname, + poll: tcp_poll, /* ok */ + ioctl: inet6_ioctl, /* must change */ + listen: inet_listen, /* ok */ + shutdown: inet_shutdown, /* ok */ + setsockopt: inet_setsockopt, /* ok */ + getsockopt: inet_getsockopt, /* ok */ + sendmsg: inet_sendmsg, /* ok */ + recvmsg: inet_recvmsg, /* ok */ + mmap: sock_no_mmap, }; struct proto_ops inet6_dgram_ops = { - PF_INET6, - - inet6_release, - inet6_bind, - inet_dgram_connect, /* ok */ - sock_no_socketpair, /* a do nothing */ - sock_no_accept, /* a do nothing */ - inet6_getname, - datagram_poll, /* ok */ - inet6_ioctl, /* must change */ - sock_no_listen, /* ok */ - inet_shutdown, /* ok */ - inet_setsockopt, /* ok */ - inet_getsockopt, /* ok */ - sock_no_fcntl, /* ok */ - inet_sendmsg, /* ok */ - inet_recvmsg, /* ok */ - sock_no_mmap, + family: PF_INET6, + + release: inet6_release, + bind: inet6_bind, + connect: inet_dgram_connect, /* ok */ + socketpair: sock_no_socketpair, /* a do nothing */ + accept: sock_no_accept, /* a do nothing */ + getname: inet6_getname, + poll: datagram_poll, /* ok */ + ioctl: inet6_ioctl, /* must change */ + listen: sock_no_listen, /* ok */ + shutdown: inet_shutdown, /* ok */ + setsockopt: inet_setsockopt, /* ok */ + getsockopt: inet_getsockopt, /* ok */ + sendmsg: inet_sendmsg, /* ok */ + recvmsg: inet_recvmsg, /* ok */ + mmap: sock_no_mmap, }; struct net_proto_family inet6_family_ops = { diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index c9be23990..22c1fa367 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c @@ -7,7 +7,7 @@ * PROC file system. This is very similar to the IPv4 version, * except it reports the sockets in the INET6 address family. * - * Version: $Id: proc.c,v 1.13 2000/01/09 02:19:55 davem Exp $ + * Version: $Id: proc.c,v 1.14 2000/04/16 01:11:37 davem Exp $ * * Authors: David S. Miller (davem@caip.rutgers.edu) * @@ -32,7 +32,7 @@ static int fold_prot_inuse(struct proto *proto) int cpu; for (cpu=0; cpu<smp_num_cpus; cpu++) - res += proto->stats[cpu].inuse; + res += proto->stats[cpu_logical_map(cpu)].inuse; return res; } @@ -138,8 +138,10 @@ static unsigned long fold_field(unsigned long *ptr, int size) unsigned long res = 0; int i; - for (i=0; i<smp_num_cpus; i++) - res += ptr[i*size]; + for (i=0; i<smp_num_cpus; i++) { + res += ptr[2*cpu_logical_map(i)*size]; + res += ptr[(2*cpu_logical_map(i)+1)*size]; + } return res; } diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index bb4ecb551..6abd7f4bf 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -7,7 +7,7 @@ * * Adapted from linux/net/ipv4/raw.c * - * $Id: raw.c,v 1.34 2000/02/27 19:51:48 davem Exp $ + * $Id: raw.c,v 1.35 2000/04/25 04:13:34 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -786,22 +786,18 @@ out: } struct proto rawv6_prot = { - rawv6_close, /* close */ - udpv6_connect, /* connect */ - udp_disconnect, /* disconnect */ - NULL, /* accept */ - NULL, /* ioctl */ - rawv6_init_sk, /* init */ - inet6_destroy_sock, /* destroy */ - NULL, /* shutdown */ - rawv6_setsockopt, /* setsockopt */ - rawv6_getsockopt, /* getsockopt */ - rawv6_sendmsg, /* sendmsg */ - rawv6_recvmsg, /* recvmsg */ - rawv6_bind, /* bind */ - rawv6_rcv_skb, /* backlog_rcv */ - raw_v6_hash, /* hash */ - raw_v6_unhash, /* unhash */ - NULL, /* get_port */ - "RAW", /* name */ + name: "RAW", + close: rawv6_close, + connect: udpv6_connect, + disconnect: udp_disconnect, + init: rawv6_init_sk, + destroy: inet6_destroy_sock, + setsockopt: rawv6_setsockopt, + getsockopt: rawv6_getsockopt, + sendmsg: rawv6_sendmsg, + recvmsg: rawv6_recvmsg, + bind: rawv6_bind, + backlog_rcv: rawv6_rcv_skb, + hash: raw_v6_hash, + unhash: raw_v6_unhash, }; diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c6fd03355..760c77cd8 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -5,7 +5,7 @@ * Authors: * Pedro Roque <roque@di.fc.ul.pt> * - * $Id: tcp_ipv6.c,v 1.122 2000/03/25 01:52:11 davem Exp $ + * $Id: tcp_ipv6.c,v 1.123 2000/04/25 04:13:34 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -2080,24 +2080,23 @@ out_no_bh: } struct proto tcpv6_prot = { - tcp_close, /* close */ - tcp_v6_connect, /* connect */ - tcp_disconnect, /* disconnect */ - tcp_accept, /* accept */ - tcp_ioctl, /* ioctl */ - tcp_v6_init_sock, /* init */ - tcp_v6_destroy_sock, /* destroy */ - tcp_shutdown, /* shutdown */ - tcp_setsockopt, /* setsockopt */ - tcp_getsockopt, /* getsockopt */ - tcp_sendmsg, /* sendmsg */ - tcp_recvmsg, /* recvmsg */ - NULL, /* bind */ - tcp_v6_do_rcv, /* backlog_rcv */ - tcp_v6_hash, /* hash */ - tcp_unhash, /* unhash */ - tcp_v6_get_port, /* get_port */ - "TCPv6", /* name */ + name: "TCPv6", + close: tcp_close, + connect: tcp_v6_connect, + disconnect: tcp_disconnect, + accept: tcp_accept, + ioctl: tcp_ioctl, + init: tcp_v6_init_sock, + destroy: tcp_v6_destroy_sock, + shutdown: tcp_shutdown, + setsockopt: tcp_setsockopt, + getsockopt: tcp_getsockopt, + sendmsg: tcp_sendmsg, + recvmsg: tcp_recvmsg, + backlog_rcv: tcp_v6_do_rcv, + hash: tcp_v6_hash, + unhash: tcp_unhash, + get_port: tcp_v6_get_port, }; static struct inet6_protocol tcpv6_protocol = diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index fed8e3aa2..5665c3225 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -7,7 +7,7 @@ * * Based on linux/ipv4/udp.c * - * $Id: udp.c,v 1.51 2000/02/27 19:51:51 davem Exp $ + * $Id: udp.c,v 1.52 2000/04/25 04:13:34 davem Exp $ * * Fixes: * Hideaki YOSHIFUJI : sin6_scope_id support @@ -972,24 +972,20 @@ out: } struct proto udpv6_prot = { - udpv6_close, /* close */ - udpv6_connect, /* connect */ - udp_disconnect, /* disconnect */ - NULL, /* accept */ - udp_ioctl, /* ioctl */ - NULL, /* init */ - inet6_destroy_sock, /* destroy */ - NULL, /* shutdown */ - ipv6_setsockopt, /* setsockopt */ - ipv6_getsockopt, /* getsockopt */ - udpv6_sendmsg, /* sendmsg */ - udpv6_recvmsg, /* recvmsg */ - NULL, /* bind */ - udpv6_queue_rcv_skb, /* backlog_rcv */ - udp_v6_hash, /* hash */ - udp_v6_unhash, /* unhash */ - udp_v6_get_port, /* get_port */ - "UDP", /* name */ + name: "UDP", + close: udpv6_close, + connect: udpv6_connect, + disconnect: udp_disconnect, + ioctl: udp_ioctl, + destroy: inet6_destroy_sock, + setsockopt: ipv6_setsockopt, + getsockopt: ipv6_getsockopt, + sendmsg: udpv6_sendmsg, + recvmsg: udpv6_recvmsg, + backlog_rcv: udpv6_queue_rcv_skb, + hash: udp_v6_hash, + unhash: udp_v6_unhash, + get_port: udp_v6_get_port, }; void __init udpv6_init(void) diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 9db90b0b8..e4c178560 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -2330,23 +2330,23 @@ static struct net_proto_family ipx_family_ops = { }; static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { - PF_IPX, - ipx_release, - ipx_bind, - ipx_connect, - sock_no_socketpair, - sock_no_accept, - ipx_getname, - datagram_poll, - ipx_ioctl, - sock_no_listen, - sock_no_shutdown, /* FIXME: We have to really support shutdown. */ - ipx_setsockopt, - ipx_getsockopt, - sock_no_fcntl, - ipx_sendmsg, - ipx_recvmsg, - sock_no_mmap + family: PF_IPX, + + release: ipx_release, + bind: ipx_bind, + connect: ipx_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: ipx_getname, + poll: datagram_poll, + ioctl: ipx_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, /* FIXME: We have to really support shutdown. */ + setsockopt: ipx_setsockopt, + getsockopt: ipx_getsockopt, + sendmsg: ipx_sendmsg, + recvmsg: ipx_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/ipx/af_spx.c b/net/ipx/af_spx.c index 1eb7a725c..75aaaa34a 100644 --- a/net/ipx/af_spx.c +++ b/net/ipx/af_spx.c @@ -884,23 +884,23 @@ static int spx_getsockopt(struct socket *sock, int level, int optname, } static struct proto_ops SOCKOPS_WRAPPED(spx_ops) = { - PF_IPX, - spx_release, - spx_bind, - spx_connect, - sock_no_socketpair, - spx_accept, - spx_getname, - spx_datagram_poll, - spx_ioctl, - spx_listen, - sock_no_shutdown, - spx_setsockopt, - spx_getsockopt, - sock_no_fcntl, - spx_sendmsg, - spx_recvmsg, - sock_no_mmap + family: PF_IPX, + + release: spx_release, + bind: spx_bind, + connect: spx_connect, + socketpair: sock_no_socketpair, + accept: spx_accept, + getname: spx_getname, + poll: spx_datagram_poll, + ioctl: spx_ioctl, + listen: spx_listen, + shutdown: sock_no_shutdown, + setsockopt: spx_setsockopt, + getsockopt: spx_getsockopt, + sendmsg: spx_sendmsg, + recvmsg: spx_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index bed8c5cc2..2ba86afcc 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1215,9 +1215,9 @@ static int irda_recvmsg_dgram(struct socket *sock, struct msghdr *msg, static void irda_data_wait(struct sock *sk) { if (!skb_peek(&sk->receive_queue)) { - sk->socket->flags |= SO_WAITDATA; + set_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags); interruptible_sleep_on(sk->sleep); - sk->socket->flags &= ~SO_WAITDATA; + clear_bit(SOCK_ASYNC_WAITDATA, &sk->socket->flags); } } @@ -1241,7 +1241,7 @@ static int irda_recvmsg_stream(struct socket *sock, struct msghdr *msg, self = sk->protinfo.irda; ASSERT(self != NULL, return -1;); - if (sock->flags & SO_ACCEPTCON) + if (sock->flags & __SO_ACCEPTCON) return(-EINVAL); if (flags & MSG_OOB) @@ -2015,88 +2015,84 @@ static struct net_proto_family irda_family_ops = }; static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = { - PF_IRDA, + family: PF_IRDA, - irda_release, - irda_bind, - irda_connect, - sock_no_socketpair, - irda_accept, - irda_getname, - irda_poll, - irda_ioctl, - irda_listen, - irda_shutdown, - irda_setsockopt, - irda_getsockopt, - sock_no_fcntl, - irda_sendmsg, - irda_recvmsg_stream, - sock_no_mmap + release: irda_release, + bind: irda_bind, + connect: irda_connect, + socketpair: sock_no_socketpair, + accept: irda_accept, + getname: irda_getname, + poll: irda_poll, + ioctl: irda_ioctl, + listen: irda_listen, + shutdown: irda_shutdown, + setsockopt: irda_setsockopt, + getsockopt: irda_getsockopt, + sendmsg: irda_sendmsg, + recvmsg: irda_recvmsg_stream, + mmap: sock_no_mmap, }; static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = { - PF_IRDA, + family: PF_IRDA, - irda_release, - irda_bind, - irda_connect, - sock_no_socketpair, - irda_accept, - irda_getname, - datagram_poll, - irda_ioctl, - irda_listen, - irda_shutdown, - irda_setsockopt, - irda_getsockopt, - sock_no_fcntl, - irda_sendmsg, - irda_recvmsg_dgram, - sock_no_mmap, + release: irda_release, + bind: irda_bind, + connect: irda_connect, + socketpair: sock_no_socketpair, + accept: irda_accept, + getname: irda_getname, + poll: datagram_poll, + ioctl: irda_ioctl, + listen: irda_listen, + shutdown: irda_shutdown, + setsockopt: irda_setsockopt, + getsockopt: irda_getsockopt, + sendmsg: irda_sendmsg, + recvmsg: irda_recvmsg_dgram, + mmap: sock_no_mmap, }; static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = { - PF_IRDA, + family: PF_IRDA, - irda_release, - irda_bind, - irda_connect, - sock_no_socketpair, - irda_accept, - irda_getname, - datagram_poll, - irda_ioctl, - irda_listen, - irda_shutdown, - irda_setsockopt, - irda_getsockopt, - sock_no_fcntl, - irda_sendmsg_dgram, - irda_recvmsg_dgram, - sock_no_mmap, + release: irda_release, + bind: irda_bind, + connect: irda_connect, + socketpair: sock_no_socketpair, + accept: irda_accept, + getname: irda_getname, + poll: datagram_poll, + ioctl: irda_ioctl, + listen: irda_listen, + shutdown: irda_shutdown, + setsockopt: irda_setsockopt, + getsockopt: irda_getsockopt, + sendmsg: irda_sendmsg_dgram, + recvmsg: irda_recvmsg_dgram, + mmap: sock_no_mmap, }; #ifdef CONFIG_IRDA_ULTRA static struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = { - PF_IRDA, + family: PF_IRDA, - irda_release, - irda_bind, - sock_no_connect, - sock_no_socketpair, - sock_no_accept, - irda_getname, - datagram_poll, - irda_ioctl, - sock_no_listen, - irda_shutdown, - irda_setsockopt, - irda_getsockopt, - sock_no_fcntl, - irda_sendmsg_ultra, - irda_recvmsg_dgram, - sock_no_mmap, + release: irda_release, + bind: irda_bind, + connect: sock_no_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: irda_getname, + poll: datagram_poll, + ioctl: irda_ioctl, + listen: sock_no_listen, + shutdown: irda_shutdown, + setsockopt: irda_setsockopt, + getsockopt: irda_getsockopt, + sendmsg: irda_sendmsg_ultra, + recvmsg: irda_recvmsg_dgram, + mmap: sock_no_mmap, }; #endif /* CONFIG_IRDA_ULTRA */ diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index ac70091af..d785983da 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c @@ -1346,7 +1346,7 @@ static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, done: if (offset >= count+begin) return 0; - *start = buf + (begin-offset); + *start = buf + (offset-begin); return ((len < begin+count-offset) ? len : begin+count-offset); } diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index b76a07274..4f4263d56 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -941,24 +941,23 @@ done: #endif struct proto_ops netlink_ops = { - PF_NETLINK, - - netlink_release, - netlink_bind, - netlink_connect, - sock_no_socketpair, - sock_no_accept, - netlink_getname, - datagram_poll, - sock_no_ioctl, - sock_no_listen, - sock_no_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - netlink_sendmsg, - netlink_recvmsg, - sock_no_mmap + family: PF_NETLINK, + + release: netlink_release, + bind: netlink_bind, + connect: netlink_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: netlink_getname, + poll: datagram_poll, + ioctl: sock_no_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: netlink_sendmsg, + recvmsg: netlink_recvmsg, + mmap: sock_no_mmap, }; struct net_proto_family netlink_family_ops = { diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index acdea4c9c..3aa133d02 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1240,24 +1240,23 @@ static struct net_proto_family nr_family_ops = }; static struct proto_ops SOCKOPS_WRAPPED(nr_proto_ops) = { - PF_NETROM, - - nr_release, - nr_bind, - nr_connect, - sock_no_socketpair, - nr_accept, - nr_getname, - datagram_poll, - nr_ioctl, - nr_listen, - sock_no_shutdown, - nr_setsockopt, - nr_getsockopt, - sock_no_fcntl, - nr_sendmsg, - nr_recvmsg, - sock_no_mmap + family: PF_NETROM, + + release: nr_release, + bind: nr_bind, + connect: nr_connect, + socketpair: sock_no_socketpair, + accept: nr_accept, + getname: nr_getname, + poll: datagram_poll, + ioctl: nr_ioctl, + listen: nr_listen, + shutdown: sock_no_shutdown, + setsockopt: nr_setsockopt, + getsockopt: nr_getsockopt, + sendmsg: nr_sendmsg, + recvmsg: nr_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/netsyms.c b/net/netsyms.c index 9a7030d7e..1b22129b8 100644 --- a/net/netsyms.c +++ b/net/netsyms.c @@ -134,7 +134,6 @@ EXPORT_SYMBOL(sock_no_listen); EXPORT_SYMBOL(sock_no_shutdown); EXPORT_SYMBOL(sock_no_getsockopt); EXPORT_SYMBOL(sock_no_setsockopt); -EXPORT_SYMBOL(sock_no_fcntl); EXPORT_SYMBOL(sock_no_sendmsg); EXPORT_SYMBOL(sock_no_recvmsg); EXPORT_SYMBOL(sock_no_mmap); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 799ec9476..2955a04f6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -5,7 +5,7 @@ * * PACKET - implements raw packet sockets. * - * Version: $Id: af_packet.c,v 1.33 2000/03/13 22:11:50 davem Exp $ + * Version: $Id: af_packet.c,v 1.34 2000/04/25 04:13:35 davem Exp $ * * Authors: Ross Biro, <bir7@leland.Stanford.Edu> * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> @@ -1723,46 +1723,44 @@ out: #ifdef CONFIG_SOCK_PACKET struct proto_ops packet_ops_spkt = { - PF_PACKET, - - packet_release, - packet_bind_spkt, - sock_no_connect, - sock_no_socketpair, - sock_no_accept, - packet_getname_spkt, - datagram_poll, - packet_ioctl, - sock_no_listen, - sock_no_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - packet_sendmsg_spkt, - packet_recvmsg, - sock_no_mmap + family: PF_PACKET, + + release: packet_release, + bind: packet_bind_spkt, + connect: sock_no_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: packet_getname_spkt, + poll: datagram_poll, + ioctl: packet_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: packet_sendmsg_spkt, + recvmsg: packet_recvmsg, + mmap: sock_no_mmap, }; #endif struct proto_ops packet_ops = { - PF_PACKET, - - packet_release, - packet_bind, - sock_no_connect, - sock_no_socketpair, - sock_no_accept, - packet_getname, - packet_poll, - packet_ioctl, - sock_no_listen, - sock_no_shutdown, - packet_setsockopt, - packet_getsockopt, - sock_no_fcntl, - packet_sendmsg, - packet_recvmsg, - packet_mmap, + family: PF_PACKET, + + release: packet_release, + bind: packet_bind, + connect: sock_no_connect, + socketpair: sock_no_socketpair, + accept: sock_no_accept, + getname: packet_getname, + poll: packet_poll, + ioctl: packet_ioctl, + listen: sock_no_listen, + shutdown: sock_no_shutdown, + setsockopt: packet_setsockopt, + getsockopt: packet_getsockopt, + sendmsg: packet_sendmsg, + recvmsg: packet_recvmsg, + mmap: packet_mmap, }; static struct net_proto_family packet_family_ops = { diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 93f1a40ab..f91baa2eb 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1410,24 +1410,23 @@ static struct net_proto_family rose_family_ops = { }; static struct proto_ops SOCKOPS_WRAPPED(rose_proto_ops) = { - PF_ROSE, - - rose_release, - rose_bind, - rose_connect, - sock_no_socketpair, - rose_accept, - rose_getname, - datagram_poll, - rose_ioctl, - rose_listen, - sock_no_shutdown, - rose_setsockopt, - rose_getsockopt, - sock_no_fcntl, - rose_sendmsg, - rose_recvmsg, - sock_no_mmap + family: PF_ROSE, + + release: rose_release, + bind: rose_bind, + connect: rose_connect, + socketpair: sock_no_socketpair, + accept: rose_accept, + getname: rose_getname, + poll: datagram_poll, + ioctl: rose_ioctl, + listen: rose_listen, + shutdown: sock_no_shutdown, + setsockopt: rose_setsockopt, + getsockopt: rose_getsockopt, + sendmsg: rose_sendmsg, + recvmsg: rose_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index e463b33ca..abf0bac91 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -512,7 +512,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) opt=kmalloc(sizeof(struct tc_gred_qopt)*MAX_DPs, GFP_KERNEL); if (opt == NULL) { - DPRINTK("gred_dump:failed to malloc for %d\n", + DPRINTK("gred_dump:failed to malloc for %Zd\n", sizeof(struct tc_gred_qopt)*MAX_DPs); goto rtattr_failure; } diff --git a/net/socket.c b/net/socket.c index fb5158241..309f76bc4 100644 --- a/net/socket.c +++ b/net/socket.c @@ -130,7 +130,7 @@ static struct file_operations socket_file_ops = { static struct net_proto_family *net_families[NPROTO]; -#ifdef __SMP__ +#ifdef CONFIG_SMP static atomic_t net_family_lockct = ATOMIC_INIT(0); static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED; @@ -561,21 +561,16 @@ int sock_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } +/* No kernel lock held - perfect */ static unsigned int sock_poll(struct file *file, poll_table * wait) { struct socket *sock; - int err; - - unlock_kernel(); - sock = socki_lookup(file->f_dentry->d_inode); /* * We can't return errors to poll, so it's either yes or no. */ - - err = sock->ops->poll(file, sock, wait); - lock_kernel(); - return err; + sock = socki_lookup(file->f_dentry->d_inode); + return sock->ops->poll(file, sock, wait); } static int sock_mmap(struct file * file, struct vm_area_struct * vma) @@ -1397,7 +1392,7 @@ int sock_fcntl(struct file *filp, unsigned int cmd, unsigned long arg) sock = socki_lookup (filp->f_dentry->d_inode); if (sock && sock->ops) - return sock->ops->fcntl(sock, cmd, arg); + return sock_no_fcntl(sock, cmd, arg); return(-EINVAL); } @@ -1618,7 +1613,7 @@ int socket_get_info(char *buffer, char **start, off_t offset, int length) int counter = 0; for (cpu=0; cpu<smp_num_cpus; cpu++) - counter += sockets_in_use[cpu].counter; + counter += sockets_in_use[cpu_logical_map(cpu)].counter; /* It can be negative, by the way. 8) */ if (counter < 0) diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index 1bf4f6070..ef5030354 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile @@ -11,13 +11,17 @@ O_TARGET := sunrpc.o O_OBJS := clnt.o xprt.o sched.o \ auth.o auth_null.o auth_unix.o \ svc.o svcsock.o svcauth.o \ - pmap_clnt.o xdr.o sysctl.o + pmap_clnt.o xdr.o OX_OBJS := sunrpc_syms.o ifeq ($(CONFIG_PROC_FS),y) O_OBJS += stats.o endif +ifeq ($(CONFIG_SYSCTL),y) + O_OBJS += sysctl.o +endif + M_OBJS := $(O_TARGET) include $(TOPDIR)/Rules.make diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c index 6afb28e88..026edcd70 100644 --- a/net/sunrpc/pmap_clnt.c +++ b/net/sunrpc/pmap_clnt.c @@ -91,8 +91,8 @@ rpc_getport_external(struct sockaddr_in *sin, __u32 prog, __u32 vers, int prot) char hostname[32]; int status; - dprintk("RPC: rpc_getport_external(%s, %d, %d, %d)\n", - in_ntoa(sin->sin_addr.s_addr), prog, vers, prot); + dprintk("RPC: rpc_getport_external(%u.%u.%u.%u, %d, %d, %d)\n", + NIPQUAD(sin->sin_addr.s_addr), prog, vers, prot); strcpy(hostname, in_ntoa(sin->sin_addr.s_addr)); if (!(pmap_clnt = pmap_create(hostname, sin, prot))) diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index da46ab910..c4d946cb3 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -1015,7 +1015,7 @@ rpciod(void *ptr) current->session = 1; current->pgrp = 1; - sprintf(current->comm, "rpciod"); + strcpy(current->comm, "rpciod"); dprintk("RPC: rpciod starting (pid %d)\n", rpciod_pid); while (rpciod_users) { diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c index 36da3b619..e53759e3e 100644 --- a/net/sunrpc/sunrpc_syms.c +++ b/net/sunrpc/sunrpc_syms.c @@ -95,6 +95,7 @@ EXPORT_SYMBOL(xdr_decode_netobj); EXPORT_SYMBOL(xdr_encode_netobj); EXPORT_SYMBOL(xdr_zero); EXPORT_SYMBOL(xdr_one); +EXPORT_SYMBOL(xdr_two); EXPORT_SYMBOL(xdr_shift_iovec); EXPORT_SYMBOL(xdr_zero_iovec); @@ -104,7 +105,9 @@ EXPORT_SYMBOL(rpc_garbage_args); EXPORT_SYMBOL(rpc_system_err); /* Debugging symbols */ +#ifdef RPC_DEBUG EXPORT_SYMBOL(rpc_debug); EXPORT_SYMBOL(nfs_debug); EXPORT_SYMBOL(nfsd_debug); EXPORT_SYMBOL(nlm_debug); +#endif diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index d99033fa5..f64653120 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -544,14 +544,14 @@ svc_tcp_accept(struct svc_sock *svsk) if (ntohs(sin.sin_port) >= 1024) { if (net_ratelimit()) printk(KERN_WARNING - "%s: connect from unprivileged port: %s:%d", + "%s: connect from unprivileged port: %u.%u.%u.%u:%d", serv->sv_name, - in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port)); + NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); goto failed; } - dprintk("%s: connect from %s:%04x\n", serv->sv_name, - in_ntoa(sin.sin_addr.s_addr), ntohs(sin.sin_port)); + dprintk("%s: connect from %u.%u.%u.%u:%04x\n", serv->sv_name, + NIPQUAD(sin.sin_addr.s_addr), ntohs(sin.sin_port)); if (!(newsvsk = svc_setup_socket(serv, newsock, &err, 0))) goto failed; @@ -915,9 +915,9 @@ svc_create_socket(struct svc_serv *serv, int protocol, struct sockaddr_in *sin) int error; int type; - dprintk("svc: svc_create_socket(%s, %d, %08x:%d)\n", + dprintk("svc: svc_create_socket(%s, %d, %u.%u.%u.%u:%d)\n", serv->sv_program->pg_name, protocol, - ntohl(sin->sin_addr.s_addr), + NIPQUAD(sin->sin_addr.s_addr), ntohs(sin->sin_port)); if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) { diff --git a/net/sunrpc/sysctl.c b/net/sunrpc/sysctl.c index 6219c3720..be49a16a1 100644 --- a/net/sunrpc/sysctl.c +++ b/net/sunrpc/sysctl.c @@ -57,7 +57,7 @@ rpc_unregister_sysctl(void) } } -int +static int proc_dodebug(ctl_table *table, int write, struct file *file, void *buffer, size_t *lenp) { diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 12a4b1eb3..15a3a6abc 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Version: $Id: af_unix.c,v 1.91 2000/03/25 01:55:34 davem Exp $ + * Version: $Id: af_unix.c,v 1.94 2000/04/25 04:13:35 davem Exp $ * * Fixes: * Linus Torvalds : Assorted bug cures. @@ -1103,6 +1103,9 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, int len, (err = unix_autobind(sock)) != 0) goto out; + err = -EMSGSIZE; + if ((unsigned)len > sk->sndbuf - 32) + goto out; skb = sock_alloc_send_skb(sk, len, 0, msg->msg_flags&MSG_DONTWAIT, &err); if (skb==NULL) @@ -1719,45 +1722,43 @@ done: #endif struct proto_ops unix_stream_ops = { - PF_UNIX, + family: PF_UNIX, - unix_release, - unix_bind, - unix_stream_connect, - unix_socketpair, - unix_accept, - unix_getname, - unix_poll, - unix_ioctl, - unix_listen, - unix_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - unix_stream_sendmsg, - unix_stream_recvmsg, - sock_no_mmap + release: unix_release, + bind: unix_bind, + connect: unix_stream_connect, + socketpair: unix_socketpair, + accept: unix_accept, + getname: unix_getname, + poll: unix_poll, + ioctl: unix_ioctl, + listen: unix_listen, + shutdown: unix_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: unix_stream_sendmsg, + recvmsg: unix_stream_recvmsg, + mmap: sock_no_mmap, }; struct proto_ops unix_dgram_ops = { - PF_UNIX, + family: PF_UNIX, - unix_release, - unix_bind, - unix_dgram_connect, - unix_socketpair, - sock_no_accept, - unix_getname, - datagram_poll, - unix_ioctl, - sock_no_listen, - unix_shutdown, - sock_no_setsockopt, - sock_no_getsockopt, - sock_no_fcntl, - unix_dgram_sendmsg, - unix_dgram_recvmsg, - sock_no_mmap + release: unix_release, + bind: unix_bind, + connect: unix_dgram_connect, + socketpair: unix_socketpair, + accept: sock_no_accept, + getname: unix_getname, + poll: datagram_poll, + ioctl: unix_ioctl, + listen: sock_no_listen, + shutdown: unix_shutdown, + setsockopt: sock_no_setsockopt, + getsockopt: sock_no_getsockopt, + sendmsg: unix_dgram_sendmsg, + recvmsg: unix_dgram_recvmsg, + mmap: sock_no_mmap, }; struct net_proto_family unix_family_ops = { diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index e042ce1d8..ebaaa7242 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -17,6 +17,9 @@ * X.25 002 Jonathan Naylor Centralised disconnect handling. * New timer architecture. * 2000-11-03 Henner Eisen MSG_EOR handling more POSIX compliant. + * 2000-22-03 Daniela Squassoni Allowed disabling/enabling of + * facilities negotiation and increased + * the throughput upper limit. */ #include <linux/config.h> @@ -811,6 +814,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *neigh, unsigned i make->protinfo.x25->source_addr = source_addr; make->protinfo.x25->neighbour = neigh; make->protinfo.x25->facilities = facilities; + make->protinfo.x25->vc_facil_mask = sk->protinfo.x25->vc_facil_mask; x25_write_internal(make, X25_CALL_ACCEPTED); @@ -1133,7 +1137,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return -EINVAL; if (facilities.winsize_in < 1 || facilities.winsize_in > 127) return -EINVAL; - if (facilities.throughput < 0x03 || facilities.throughput > 0x2C) + if (facilities.throughput < 0x03 || facilities.throughput > 0xDD) return -EINVAL; if (facilities.reverse != 0 && facilities.reverse != 1) return -EINVAL; @@ -1239,24 +1243,23 @@ struct net_proto_family x25_family_ops = { }; static struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = { - AF_X25, - - x25_release, - x25_bind, - x25_connect, - sock_no_socketpair, - x25_accept, - x25_getname, - datagram_poll, - x25_ioctl, - x25_listen, - sock_no_shutdown, - x25_setsockopt, - x25_getsockopt, - sock_no_fcntl, - x25_sendmsg, - x25_recvmsg, - sock_no_mmap + family: AF_X25, + + release: x25_release, + bind: x25_bind, + connect: x25_connect, + socketpair: sock_no_socketpair, + accept: x25_accept, + getname: x25_getname, + poll: datagram_poll, + ioctl: x25_ioctl, + listen: x25_listen, + shutdown: sock_no_shutdown, + setsockopt: x25_setsockopt, + getsockopt: x25_getsockopt, + sendmsg: x25_sendmsg, + recvmsg: x25_recvmsg, + mmap: sock_no_mmap, }; #include <linux/smp_lock.h> diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 18de2da1a..ad41d1cde 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c @@ -14,6 +14,8 @@ * * History * X.25 001 Split from x25_subr.c + * mar/20/00 Daniela Squassoni Disabling/enabling of facilities + * negotiation. */ #include <linux/config.h> @@ -43,12 +45,13 @@ * Parse a set of facilities into the facilities structure. Unrecognised * facilities are written to the debug log file. */ -int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) +int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities, unsigned long *vc_fac_mask) { unsigned int len; unsigned char *p = skb->data; len = *p++; + *vc_fac_mask = 0; while (len > 0) { switch (*p & X25_FAC_CLASS_MASK) { @@ -56,9 +59,11 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) switch (*p) { case X25_FAC_REVERSE: facilities->reverse = (p[1] & 0x01); + *vc_fac_mask |= X25_MASK_REVERSE; break; case X25_FAC_THROUGHPUT: facilities->throughput = p[1]; + *vc_fac_mask |= X25_MASK_THROUGHPUT; break; default: printk(KERN_DEBUG "X.25: unknown facility %02X, value %02X\n", p[0], p[1]); @@ -73,10 +78,12 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) case X25_FAC_PACKET_SIZE: facilities->pacsize_in = p[1]; facilities->pacsize_out = p[2]; + *vc_fac_mask |= X25_MASK_PACKET_SIZE; break; case X25_FAC_WINDOW_SIZE: facilities->winsize_in = p[1]; facilities->winsize_out = p[2]; + *vc_fac_mask |= X25_MASK_WINDOW_SIZE; break; default: printk(KERN_DEBUG "X.25: unknown facility %02X, values %02X, %02X\n", p[0], p[1], p[2]); @@ -106,28 +113,34 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities) /* * Create a set of facilities. */ -int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities) +int x25_create_facilities(unsigned char *buffer, struct x25_facilities *facilities, unsigned long facil_mask) { unsigned char *p = buffer + 1; int len; - if (facilities->reverse != 0) { + if (facil_mask == 0) { + buffer [0] = 0; /* length of the facilities field in call_req or call_accept packets */ + len = 1; /* 1 byte for the length field */ + return len; + } + + if ((facilities->reverse != 0) && (facil_mask & X25_MASK_REVERSE)) { *p++ = X25_FAC_REVERSE; *p++ = (facilities->reverse) ? 0x01 : 0x00; } - if (facilities->throughput != 0) { + if ((facilities->throughput != 0) && (facil_mask & X25_MASK_THROUGHPUT)) { *p++ = X25_FAC_THROUGHPUT; *p++ = facilities->throughput; } - if (facilities->pacsize_in != 0 || facilities->pacsize_out != 0) { + if ((facilities->pacsize_in != 0 || facilities->pacsize_out != 0) && (facil_mask & X25_MASK_PACKET_SIZE)) { *p++ = X25_FAC_PACKET_SIZE; *p++ = (facilities->pacsize_in == 0) ? facilities->pacsize_out : facilities->pacsize_in; *p++ = (facilities->pacsize_out == 0) ? facilities->pacsize_in : facilities->pacsize_out; } - if (facilities->winsize_in != 0 || facilities->winsize_out != 0) { + if ((facilities->winsize_in != 0 || facilities->winsize_out != 0) && (facil_mask & X25_MASK_WINDOW_SIZE)) { *p++ = X25_FAC_WINDOW_SIZE; *p++ = (facilities->winsize_in == 0) ? facilities->winsize_out : facilities->winsize_in; *p++ = (facilities->winsize_out == 0) ? facilities->winsize_in : facilities->winsize_out; @@ -156,7 +169,7 @@ int x25_negotiate_facilities(struct sk_buff *skb, struct sock *sk, struct x25_fa *new = *ours; - len = x25_parse_facilities(skb, &theirs); + len = x25_parse_facilities(skb, &theirs, &sk->protinfo.x25->vc_facil_mask); /* * They want reverse charging, we won't accept it. diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index a8a2905fe..5110d327a 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c @@ -13,9 +13,11 @@ * 2 of the License, or (at your option) any later version. * * History - * X.25 001 Jonathan Naylor Started coding. - * X.25 002 Jonathan Naylor Centralised disconnection code. - * New timer architecture. + * X.25 001 Jonathan Naylor Started coding. + * X.25 002 Jonathan Naylor Centralised disconnection code. + * New timer architecture. + * mar/20/00 Daniela Squassoni Disabling/enabling of facilities + * negotiation. */ #include <linux/config.h> @@ -111,7 +113,7 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp */ skb_pull(skb, X25_STD_MIN_LEN); skb_pull(skb, x25_addr_ntoa(skb->data, &source_addr, &dest_addr)); - skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities)); + skb_pull(skb, x25_parse_facilities(skb, &sk->protinfo.x25->facilities, &sk->protinfo.x25->vc_facil_mask)); /* * Copy any Call User Data. */ diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c index d33dc63c3..34d065b83 100644 --- a/net/x25/x25_link.c +++ b/net/x25/x25_link.c @@ -13,8 +13,10 @@ * 2 of the License, or (at your option) any later version. * * History - * X.25 001 Jonathan Naylor Started coding. - * X.25 002 Jonathan Naylor New timer architecture. + * X.25 001 Jonathan Naylor Started coding. + * X.25 002 Jonathan Naylor New timer architecture. + * mar/20/00 Daniela Squassoni Disabling/enabling of facilities + * negotiation. */ #include <linux/config.h> @@ -293,6 +295,7 @@ void x25_link_device_up(struct net_device *dev) x25_neigh->dev = dev; x25_neigh->state = X25_LINK_STATE_0; x25_neigh->extended = 0; + x25_neigh->global_facil_mask = (X25_MASK_REVERSE | X25_MASK_THROUGHPUT | X25_MASK_PACKET_SIZE | X25_MASK_WINDOW_SIZE); /* enables negotiation */ x25_neigh->t20 = sysctl_x25_restart_request_timeout; save_flags(flags); cli(); @@ -377,6 +380,8 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg) switch (cmd) { case SIOCX25GSUBSCRIP: + if (copy_from_user(&x25_subscr, arg, sizeof(struct x25_subscrip_struct))) + return -EFAULT; if ((dev = x25_dev_get(x25_subscr.device)) == NULL) return -EINVAL; if ((x25_neigh = x25_get_neigh(dev)) == NULL) { @@ -385,6 +390,7 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg) } dev_put(dev); x25_subscr.extended = x25_neigh->extended; + x25_subscr.global_facil_mask = x25_neigh->global_facil_mask; if (copy_to_user(arg, &x25_subscr, sizeof(struct x25_subscrip_struct))) return -EFAULT; break; @@ -402,6 +408,7 @@ int x25_subscr_ioctl(unsigned int cmd, void *arg) if (x25_subscr.extended != 0 && x25_subscr.extended != 1) return -EINVAL; x25_neigh->extended = x25_subscr.extended; + x25_neigh->global_facil_mask = x25_subscr.global_facil_mask; break; default: diff --git a/net/x25/x25_subr.c b/net/x25/x25_subr.c index 8b055e40e..25a700af9 100644 --- a/net/x25/x25_subr.c +++ b/net/x25/x25_subr.c @@ -13,8 +13,10 @@ * 2 of the License, or (at your option) any later version. * * History - * X.25 001 Jonathan Naylor Started coding. - * X.25 002 Jonathan Naylor Centralised disconnection processing. + * X.25 001 Jonathan Naylor Started coding. + * X.25 002 Jonathan Naylor Centralised disconnection processing. + * mar/20/00 Daniela Squassoni Disabling/enabling of facilities + * negotiation. */ #include <linux/config.h> @@ -206,7 +208,7 @@ void x25_write_internal(struct sock *sk, int frametype) len = x25_addr_aton(addresses, &sk->protinfo.x25->dest_addr, &sk->protinfo.x25->source_addr); dptr = skb_put(skb, len); memcpy(dptr, addresses, len); - len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities); + len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->neighbour->global_facil_mask); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength); @@ -218,7 +220,7 @@ void x25_write_internal(struct sock *sk, int frametype) dptr = skb_put(skb, 2); *dptr++ = X25_CALL_ACCEPTED; *dptr++ = 0x00; /* Address lengths */ - len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities); + len = x25_create_facilities(facilities, &sk->protinfo.x25->facilities, sk->protinfo.x25->vc_facil_mask); dptr = skb_put(skb, len); memcpy(dptr, facilities, len); dptr = skb_put(skb, sk->protinfo.x25->calluserdata.cudlength); |