diff options
Diffstat (limited to 'net')
77 files changed, 2338 insertions, 2228 deletions
diff --git a/net/Kconfig b/net/Kconfig index 9296b269d67..bc603d9aea5 100644 --- a/net/Kconfig +++ b/net/Kconfig @@ -150,6 +150,7 @@ endif source "net/dccp/Kconfig" source "net/sctp/Kconfig" +source "net/tipc/Kconfig" source "net/atm/Kconfig" source "net/bridge/Kconfig" source "net/8021q/Kconfig" @@ -159,7 +160,6 @@ source "net/ipx/Kconfig" source "drivers/net/appletalk/Kconfig" source "net/x25/Kconfig" source "net/lapb/Kconfig" -source "net/tipc/Kconfig" config NET_DIVERT bool "Frame Diverter (EXPERIMENTAL)" diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c index f158fe67dd6..dc5d0b2427c 100644 --- a/net/bridge/netfilter/ebt_ip.c +++ b/net/bridge/netfilter/ebt_ip.c @@ -92,7 +92,9 @@ static int ebt_ip_check(const char *tablename, unsigned int hookmask, if (info->invflags & EBT_IP_PROTO) return -EINVAL; if (info->protocol != IPPROTO_TCP && - info->protocol != IPPROTO_UDP) + info->protocol != IPPROTO_UDP && + info->protocol != IPPROTO_SCTP && + info->protocol != IPPROTO_DCCP) return -EINVAL; } if (info->bitmask & EBT_IP_DPORT && info->dport[0] > info->dport[1]) diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index a29c1232c42..0128fbbe232 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c @@ -95,7 +95,9 @@ ebt_log_packet(unsigned int pf, unsigned int hooknum, "tos=0x%02X, IP proto=%d", NIPQUAD(ih->saddr), NIPQUAD(ih->daddr), ih->tos, ih->protocol); if (ih->protocol == IPPROTO_TCP || - ih->protocol == IPPROTO_UDP) { + ih->protocol == IPPROTO_UDP || + ih->protocol == IPPROTO_SCTP || + ih->protocol == IPPROTO_DCCP) { struct tcpudphdr _ports, *pptr; pptr = skb_header_pointer(skb, ih->ihl*4, diff --git a/net/core/filter.c b/net/core/filter.c index a52665f7522..9540946a48f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -74,7 +74,6 @@ static inline void *load_pointer(struct sk_buff *skb, int k, * filtering, filter is the array of filter instructions, and * len is the number of filter blocks in the array. */ - unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int flen) { struct sock_filter *fentry; /* We walk down these */ @@ -175,7 +174,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int continue; case BPF_LD|BPF_W|BPF_ABS: k = fentry->k; - load_w: +load_w: ptr = load_pointer(skb, k, 4, &tmp); if (ptr != NULL) { A = ntohl(*(u32 *)ptr); @@ -184,7 +183,7 @@ unsigned int sk_run_filter(struct sk_buff *skb, struct sock_filter *filter, int break; case BPF_LD|BPF_H|BPF_ABS: k = fentry->k; - load_h: +load_h: ptr = load_pointer(skb, k, 2, &tmp); if (ptr != NULL) { A = ntohs(*(u16 *)ptr); @@ -374,7 +373,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) case BPF_JMP|BPF_JSET|BPF_K: case BPF_JMP|BPF_JSET|BPF_X: /* for conditionals both must be safe */ - if (pc + ftest->jt + 1 >= flen || + if (pc + ftest->jt + 1 >= flen || pc + ftest->jf + 1 >= flen) return -EINVAL; break; @@ -384,7 +383,7 @@ int sk_chk_filter(struct sock_filter *filter, int flen) } } - return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; + return (BPF_CLASS(filter[flen - 1].code) == BPF_RET) ? 0 : -EINVAL; } /** @@ -404,8 +403,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) int err; /* Make sure new filter is there and in the right amounts. */ - if (fprog->filter == NULL) - return -EINVAL; + if (fprog->filter == NULL) + return -EINVAL; fp = sock_kmalloc(sk, fsize+sizeof(*fp), GFP_KERNEL); if (!fp) diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 281a632fa6a..ea51f8d02eb 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -703,7 +703,7 @@ int netpoll_setup(struct netpoll *np) } } - if (!memcmp(np->local_mac, "\0\0\0\0\0\0", 6) && ndev->dev_addr) + if (is_zero_ether_addr(np->local_mac) && ndev->dev_addr) memcpy(np->local_mac, ndev->dev_addr, 6); if (!np->local_ip) { diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 39063122fbb..da16f8fd149 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -139,6 +139,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/wait.h> +#include <linux/etherdevice.h> #include <net/checksum.h> #include <net/ipv6.h> #include <net/addrconf.h> @@ -281,8 +282,8 @@ struct pktgen_dev { __u32 src_mac_count; /* How many MACs to iterate through */ __u32 dst_mac_count; /* How many MACs to iterate through */ - unsigned char dst_mac[6]; - unsigned char src_mac[6]; + unsigned char dst_mac[ETH_ALEN]; + unsigned char src_mac[ETH_ALEN]; __u32 cur_dst_mac_offset; __u32 cur_src_mac_offset; @@ -594,16 +595,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) seq_puts(seq, " src_mac: "); - if ((pkt_dev->src_mac[0] == 0) && - (pkt_dev->src_mac[1] == 0) && - (pkt_dev->src_mac[2] == 0) && - (pkt_dev->src_mac[3] == 0) && - (pkt_dev->src_mac[4] == 0) && - (pkt_dev->src_mac[5] == 0)) - + if (is_zero_ether_addr(pkt_dev->src_mac)) for (i = 0; i < 6; i++) seq_printf(seq, "%02X%s", pkt_dev->odev->dev_addr[i], i == 5 ? " " : ":"); - else for (i = 0; i < 6; i++) seq_printf(seq, "%02X%s", pkt_dev->src_mac[i], i == 5 ? " " : ":"); @@ -1189,9 +1183,9 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer } if (!strcmp(name, "dst_mac")) { char *v = valstr; - unsigned char old_dmac[6]; + unsigned char old_dmac[ETH_ALEN]; unsigned char *m = pkt_dev->dst_mac; - memcpy(old_dmac, pkt_dev->dst_mac, 6); + memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); len = strn_len(&user_buffer[i], sizeof(valstr) - 1); if (len < 0) { return len; } @@ -1220,8 +1214,8 @@ static ssize_t pktgen_if_write(struct file *file, const char __user *user_buffer } /* Set up Dest MAC */ - if (memcmp(old_dmac, pkt_dev->dst_mac, 6) != 0) - memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6); + if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) + memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); sprintf(pg_result, "OK: dstmac"); return count; @@ -1560,17 +1554,11 @@ static void pktgen_setup_inject(struct pktgen_dev *pkt_dev) /* Default to the interface's mac if not explicitly set. */ - if ((pkt_dev->src_mac[0] == 0) && - (pkt_dev->src_mac[1] == 0) && - (pkt_dev->src_mac[2] == 0) && - (pkt_dev->src_mac[3] == 0) && - (pkt_dev->src_mac[4] == 0) && - (pkt_dev->src_mac[5] == 0)) { + if (is_zero_ether_addr(pkt_dev->src_mac)) + memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, ETH_ALEN); - memcpy(&(pkt_dev->hh[6]), pkt_dev->odev->dev_addr, 6); - } /* Set up Dest MAC */ - memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, 6); + memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); /* Set up pkt size */ pkt_dev->cur_pkt_size = pkt_dev->min_pkt_size; @@ -1872,13 +1860,14 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev, */ mod_cur_headers(pkt_dev); - skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + 16, GFP_ATOMIC); + datalen = (odev->hard_header_len + 16) & ~0xf; + skb = alloc_skb(pkt_dev->cur_pkt_size + 64 + datalen, GFP_ATOMIC); if (!skb) { sprintf(pkt_dev->result, "No memory"); return NULL; } - skb_reserve(skb, 16); + skb_reserve(skb, datalen); /* Reserve for ethernet and IP header */ eth = (__u8 *) skb_push(skb, 14); diff --git a/net/dccp/ackvec.c b/net/dccp/ackvec.c index ce9cb77c5c2..2c77dafbd09 100644 --- a/net/dccp/ackvec.c +++ b/net/dccp/ackvec.c @@ -144,7 +144,7 @@ static inline int dccp_ackvec_set_buf_head_state(struct dccp_ackvec *av, const unsigned char state) { unsigned int gap; - signed long new_head; + long new_head; if (av->dccpav_vec_len + packets > av->dccpav_buf_len) return -ENOBUFS; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 192092b89e5..d8ce7133cd8 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -233,7 +233,18 @@ static int is_in(struct ip_mc_list *pmc, struct ip_sf_list *psf, int type, case IGMPV3_MODE_IS_EXCLUDE: if (gdeleted || sdeleted) return 0; - return !(pmc->gsquery && !psf->sf_gsresp); + if (!(pmc->gsquery && !psf->sf_gsresp)) { + if (pmc->sfmode == MCAST_INCLUDE) + return 1; + /* don't include if this source is excluded + * in all filters + */ + if (psf->sf_count[MCAST_INCLUDE]) + return type == IGMPV3_MODE_IS_INCLUDE; + return pmc->sfcount[MCAST_EXCLUDE] == + psf->sf_count[MCAST_EXCLUDE]; + } + return 0; case IGMPV3_CHANGE_TO_INCLUDE: if (gdeleted || sdeleted) return 0; @@ -385,7 +396,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, struct igmpv3_report *pih; struct igmpv3_grec *pgr = NULL; struct ip_sf_list *psf, *psf_next, *psf_prev, **psf_list; - int scount, first, isquery, truncate; + int scount, stotal, first, isquery, truncate; if (pmc->multiaddr == IGMP_ALL_HOSTS) return skb; @@ -395,25 +406,13 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, truncate = type == IGMPV3_MODE_IS_EXCLUDE || type == IGMPV3_CHANGE_TO_EXCLUDE; + stotal = scount = 0; + psf_list = sdeleted ? &pmc->tomb : &pmc->sources; - if (!*psf_list) { - if (type == IGMPV3_ALLOW_NEW_SOURCES || - type == IGMPV3_BLOCK_OLD_SOURCES) - return skb; - if (pmc->crcount || isquery) { - /* make sure we have room for group header and at - * least one source. - */ - if (skb && AVAILABLE(skb) < sizeof(struct igmpv3_grec)+ - sizeof(__u32)) { - igmpv3_sendpack(skb); - skb = NULL; /* add_grhead will get a new one */ - } - skb = add_grhead(skb, pmc, type, &pgr); - } - return skb; - } + if (!*psf_list) + goto empty_source; + pih = skb ? (struct igmpv3_report *)skb->h.igmph : NULL; /* EX and TO_EX get a fresh packet, if needed */ @@ -426,7 +425,6 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, } } first = 1; - scount = 0; psf_prev = NULL; for (psf=*psf_list; psf; psf=psf_next) { u32 *psrc; @@ -460,7 +458,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, } psrc = (u32 *)skb_put(skb, sizeof(u32)); *psrc = psf->sf_inaddr; - scount++; + scount++; stotal++; if ((type == IGMPV3_ALLOW_NEW_SOURCES || type == IGMPV3_BLOCK_OLD_SOURCES) && psf->sf_crcount) { psf->sf_crcount--; @@ -475,6 +473,21 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ip_mc_list *pmc, } psf_prev = psf; } + +empty_source: + if (!stotal) { + if (type == IGMPV3_ALLOW_NEW_SOURCES || + type == IGMPV3_BLOCK_OLD_SOURCES) + return skb; + if (pmc->crcount || isquery) { + /* make sure we have room for group header */ + if (skb && AVAILABLE(skb)<sizeof(struct igmpv3_grec)) { + igmpv3_sendpack(skb); + skb = NULL; /* add_grhead will get a new one */ + } + skb = add_grhead(skb, pmc, type, &pgr); + } + } if (pgr) pgr->grec_nsrcs = htons(scount); @@ -557,11 +570,11 @@ static void igmpv3_send_cr(struct in_device *in_dev) skb = add_grec(skb, pmc, dtype, 1, 1); } if (pmc->crcount) { - pmc->crcount--; if (pmc->sfmode == MCAST_EXCLUDE) { type = IGMPV3_CHANGE_TO_INCLUDE; skb = add_grec(skb, pmc, type, 1, 0); } + pmc->crcount--; if (pmc->crcount == 0) { igmpv3_clear_zeros(&pmc->tomb); igmpv3_clear_zeros(&pmc->sources); @@ -594,12 +607,12 @@ static void igmpv3_send_cr(struct in_device *in_dev) /* filter mode changes */ if (pmc->crcount) { - pmc->crcount--; if (pmc->sfmode == MCAST_EXCLUDE) type = IGMPV3_CHANGE_TO_EXCLUDE; else type = IGMPV3_CHANGE_TO_INCLUDE; skb = add_grec(skb, pmc, type, 0, 0); + pmc->crcount--; } spin_unlock_bh(&pmc->lock); } @@ -735,11 +748,43 @@ static void igmp_timer_expire(unsigned long data) ip_ma_put(im); } -static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) +/* mark EXCLUDE-mode sources */ +static int igmp_xmarksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) +{ + struct ip_sf_list *psf; + int i, scount; + + scount = 0; + for (psf=pmc->sources; psf; psf=psf->sf_next) { + if (scount == nsrcs) + break; + for (i=0; i<nsrcs; i++) { + /* skip inactive filters */ + if (pmc->sfcount[MCAST_INCLUDE] || + pmc->sfcount[MCAST_EXCLUDE] != + psf->sf_count[MCAST_EXCLUDE]) + continue; + if (srcs[i] == psf->sf_inaddr) { + scount++; + break; + } + } + } + pmc->gsquery = 0; + if (scount == nsrcs) /* all sources excluded */ + return 0; + return 1; +} + +static int igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) { struct ip_sf_list *psf; int i, scount; + if (pmc->sfmode == MCAST_EXCLUDE) + return igmp_xmarksources(pmc, nsrcs, srcs); + + /* mark INCLUDE-mode sources */ scount = 0; for (psf=pmc->sources; psf; psf=psf->sf_next) { if (scount == nsrcs) @@ -751,6 +796,12 @@ static void igmp_marksources(struct ip_mc_list *pmc, int nsrcs, __u32 *srcs) break; } } + if (!scount) { + pmc->gsquery = 0; + return 0; + } + pmc->gsquery = 1; + return 1; } static void igmp_heard_report(struct in_device *in_dev, u32 group) @@ -845,6 +896,8 @@ static void igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb, */ read_lock(&in_dev->mc_list_lock); for (im=in_dev->mc_list; im!=NULL; im=im->next) { |