static void bitmap_ipmac_gc(unsigned long ul_set) { struct ip_set *set = (struct ip_set *) ul_set; struct bitmap_ipmac *map = set->data; struct ipmac_telem *elem; u32 id, last = map->last_ip - map->first_ip; /* We run parallel with other readers (test element) * but adding/deleting new entries is locked out */ read_lock_bh(&set->lock); for (id = 0; id <= last; id++) { elem = bitmap_ipmac_elem(map, id); if (elem->match == MAC_FILLED && ip_set_timeout_expired(elem->timeout)) elem->match = MAC_EMPTY; } read_unlock_bh(&set->lock); map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; add_timer(&map->gc); }
static inline int lapd_pass_frame_to_socket_te( struct sk_buff *skb) { struct sock *sk; struct hlist_node *node; struct lapd_data_hdr *hdr = (struct lapd_data_hdr *)skb->data; struct lapd_device *dev = to_lapd_dev(skb->dev); int queued = 0; read_lock_bh(&lapd_hash_lock); sk_for_each(sk, node, lapd_get_hash(dev)) { struct lapd_sock *lapd_sock = to_lapd_sock(sk); if (lapd_sock->dev == dev && (sk->sk_state == LAPD_SK_STATE_NORMAL_DLC || sk->sk_state == LAPD_SK_STATE_BROADCAST_DLC) && lapd_sock->sapi == hdr->addr.sapi && lapd_sock->tei == hdr->addr.tei) { struct sk_buff *new_skb; if (!queued) { new_skb = skb; queued = TRUE; } else { new_skb = skb_clone(skb, GFP_ATOMIC); } new_skb->sk = sk; queued = lapd_pass_frame_to_socket( to_lapd_sock(sk), new_skb); } } read_unlock_bh(&lapd_hash_lock); return queued; }
int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n) { int t = 0; int i; struct neighbour *neigh; struct dn_neigh *dn; struct neigh_table *tbl = &dn_neigh_table; unsigned char *rs = ptr; struct dn_dev *dn_db = (struct dn_dev *)dev->dn_ptr; read_lock_bh(&tbl->lock); for(i = 0; i < NEIGH_HASHMASK; i++) { for(neigh = tbl->hash_buckets[i]; neigh != NULL; neigh = neigh->next) { if (neigh->dev != dev) continue; dn = (struct dn_neigh *)neigh; if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2))) continue; if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2)) continue; if (t == n) rs = dn_find_slot(ptr, n, dn->priority); else t++; if (rs == NULL) continue; dn_dn2eth(rs, dn->addr); rs += 6; *rs = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0; *rs |= dn->priority; rs++; } } read_unlock_bh(&tbl->lock); return t; }
int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr) { struct inet6_dev *idev; int err = -EADDRNOTAVAIL; read_lock(&addrconf_lock); if ((idev = __in6_dev_get(dev)) != NULL) { struct inet6_ifaddr *ifp; read_lock_bh(&idev->lock); for (ifp=idev->addr_list; ifp; ifp=ifp->if_next) { if (ifp->scope == IFA_LINK && !(ifp->flags&IFA_F_TENTATIVE)) { ipv6_addr_copy(addr, &ifp->addr); err = 0; break; } } read_unlock_bh(&idev->lock); } read_unlock(&addrconf_lock); return err; }
s32 nd_flush_by_slot (u32 vsm_board) { s32 chain = 0; struct neigh_table *tbl = &nd_tbl; read_lock_bh (&tbl->lock); for (chain = 0; chain <= tbl->hash_mask; chain++) { struct neighbour *n; for (n = tbl->hash_buckets[chain].neighbour; n; n = n->next) { if (n->neigh_flags & NEIGH_MSWITCH) { n->neigh_index[vsm_board - g_board_offset] = 0; } } } read_unlock_bh(&tbl->lock); return 0; }
static inline int ip6_output_finish(struct sk_buff *skb) { struct dst_entry *dst = skb->dst; struct hh_cache *hh = dst->hh; if (hh) { int hh_alen; read_lock_bh(&hh->hh_lock); hh_alen = HH_DATA_ALIGN(hh->hh_len); memcpy(skb->data - hh_alen, hh->hh_data, hh_alen); read_unlock_bh(&hh->hh_lock); skb_push(skb, hh->hh_len); return hh->hh_output(skb); } else if (dst->neighbour) return dst->neighbour->output(skb); kfree_skb(skb); return -EINVAL; }
static void smc_lgr_free_work(struct work_struct *work) { struct smc_link_group *lgr = container_of(to_delayed_work(work), struct smc_link_group, free_work); bool conns; spin_lock_bh(&smc_lgr_list.lock); if (list_empty(&lgr->list)) goto free; read_lock_bh(&lgr->conns_lock); conns = RB_EMPTY_ROOT(&lgr->conns_all); read_unlock_bh(&lgr->conns_lock); if (!conns) { /* number of lgr connections is no longer zero */ spin_unlock_bh(&smc_lgr_list.lock); return; } list_del_init(&lgr->list); /* remove from smc_lgr_list */ free: spin_unlock_bh(&smc_lgr_list.lock); smc_lgr_free(lgr); }
/* Call this every MPC-p5 seconds. */ static void refresh_entries(struct mpoa_client *client) { struct timeval now; struct in_cache_entry *entry = client->in_cache; ddprintk("mpoa: mpoa_caches.c: refresh_entries\n"); do_gettimeofday(&now); 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"); entry->entry_state = INGRESS_REFRESHING; } } entry = entry->next; } read_unlock_bh(&client->ingress_lock); }
static int ip6_onlink(struct in6_addr *addr, struct net_device *dev) { struct inet6_dev *idev; struct inet6_ifaddr *ifa; int onlink; onlink = 0; rcu_read_lock(); idev = __in6_dev_get(dev); if (idev) { read_lock_bh(&idev->lock); for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { onlink = ipv6_prefix_equal(addr, &ifa->addr, ifa->prefix_len); if (onlink) break; } read_unlock_bh(&idev->lock); } rcu_read_unlock(); return onlink; }
s32 nd_restore_by_slot (u32 vsm_board) { s32 chain = 0; s32 ret = 0; struct neigh_table *tbl = &nd_tbl; read_lock_bh (&tbl->lock); for (chain = 0; chain <= tbl->hash_mask; chain++) { struct neighbour *n; for (n = tbl->hash_buckets[chain].neighbour; n; n = n->next) { if (n->neigh_flags & NEIGH_MSWITCH) { ret = mswitch_nd_add (n, vsm_board); } } } read_unlock_bh(&tbl->lock); return 0; }
static struct dst_entry * __xfrm6_find_bundle(struct flowi *fl, struct rtable *rt, struct xfrm_policy *policy) { struct dst_entry *dst; u32 ndisc_bit = 0; if (fl->proto == IPPROTO_ICMPV6 && (fl->fl_icmp_type == NDISC_NEIGHBOUR_ADVERTISEMENT || fl->fl_icmp_type == NDISC_NEIGHBOUR_SOLICITATION || fl->fl_icmp_type == NDISC_ROUTER_SOLICITATION)) ndisc_bit = RTF_NDISC; /* Still not clear if we should set fl->fl6_{src,dst}... */ read_lock_bh(&policy->lock); for (dst = policy->bundles; dst; dst = dst->next) { struct xfrm_dst *xdst = (struct xfrm_dst*)dst; struct in6_addr fl_dst_prefix, fl_src_prefix; if ((xdst->u.rt6.rt6i_flags & RTF_NDISC) != ndisc_bit) continue; ipv6_addr_prefix(&fl_dst_prefix, &fl->fl6_dst, xdst->u.rt6.rt6i_dst.plen); ipv6_addr_prefix(&fl_src_prefix, &fl->fl6_src, xdst->u.rt6.rt6i_src.plen); if (!ipv6_addr_cmp(&xdst->u.rt6.rt6i_dst.addr, &fl_dst_prefix) && !ipv6_addr_cmp(&xdst->u.rt6.rt6i_src.addr, &fl_src_prefix) && __xfrm6_bundle_ok(xdst, fl)) { dst_clone(dst); break; } } read_unlock_bh(&policy->lock); return dst; }
static int send_to_user(struct packet_info *info) { int ret; int size; sk_buff_data_t old_tail; struct sk_buff *skb; struct nlmsghdr *nlh; struct packet_info *packet; size = NLMSG_SPACE(sizeof(*info)); skb = alloc_skb(size, GFP_ATOMIC); old_tail = skb->tail; nlh = nlmsg_put(skb, 0, 0, NL_K_MSG, size - sizeof(*nlh), NLM_F_REQUEST); if (!nlh) { if (skb) { kfree_skb(skb); return -1; } } packet = NLMSG_DATA(nlh); memset(packet, 0, sizeof(struct packet_info)); packet->src = info->src; packet->dst = info->dst; nlh->nlmsg_len = skb->tail - old_tail; NETLINK_CB(skb).dst_group = 0; read_lock_bh(&user_proc.lock); ret = netlink_unicast(nlfd, skb, user_proc.pid, MSG_DONTWAIT); read_unlock_bh(&user_proc.lock); return ret; }
static void psock_write_space(struct sock *sk) { struct kcm_psock *psock; struct kcm_mux *mux; struct kcm_sock *kcm; read_lock_bh(&sk->sk_callback_lock); psock = (struct kcm_psock *)sk->sk_user_data; if (unlikely(!psock)) goto out; mux = psock->mux; spin_lock_bh(&mux->lock); /* Check if the socket is reserved so someone is waiting for sending. */ kcm = psock->tx_kcm; if (kcm && !unlikely(kcm->tx_stopped)) queue_work(kcm_wq, &kcm->tx_work); spin_unlock_bh(&mux->lock); out: read_unlock_bh(&sk->sk_callback_lock); }
static int send_to_user(struct packet_info *info) { int ret; int size; unsigned char *old_tail; struct sk_buff *skb; struct nlmsghdr *nlh; struct packet_info *packet; size = NLMSG_SPACE(sizeof(*info)); skb = alloc_skb(size, GFP_ATOMIC); old_tail = skb->tail; nlh = NLMSG_PUT(skb, 0, 0, SIPFW_K_MSG, size-sizeof(*nlh)); packet = NLMSG_DATA(nlh); memset(packet, 0, sizeof(struct packet_info)); packet->src = info->src; packet->dest = info->dest; nlh->nlmsg_len = skb->tail - old_tail; NETLINK_CB(skb).dst_group = 0; read_lock_bh(&user_proc.lock); ret = netlink_unicast(nlfd, skb, user_proc.pid, MSG_DONTWAIT); read_unlock_bh(&user_proc.lock); return ret; nlmsg_failure: if(skb) kfree_skb(skb); return -1; }
struct sk_buff *tipc_bearer_get_names(void) { struct sk_buff *buf; struct tipc_bearer *b_ptr; int i, j; buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME)); if (!buf) return NULL; read_lock_bh(&tipc_net_lock); for (i = 0; i < media_count; i++) { for (j = 0; j < MAX_BEARERS; j++) { b_ptr = &tipc_bearers[j]; if (b_ptr->active && (b_ptr->media == media_list[i])) { tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, b_ptr->name, strlen(b_ptr->name) + 1); } } } read_unlock_bh(&tipc_net_lock); return buf; }
s32 mpls_echo_input(struct sk_buff * skb) { s32 err = 0; s32 temp = 0; u32 saddr = 0; struct timeval tv; mpls_echo_hdr * echo; struct ethhdr * eth ; struct fib_mg_res res ; struct iphdr *iph = skb->nh.iph; struct udphdr * udph = skb->h.uh; echo = (mpls_echo_hdr *)(skb->data + sizeof(struct udphdr)); skb_push(skb, iph->ihl * 4); err = fib_mg_lookup(if_dev_vrf(skb->dev)->vrf_id, iph->saddr, 32, &res); if (err) { printk("mpls_echo_input -fib_mg_lookup drop.\n"); goto drop; } temp = iph->daddr; iph->daddr = iph->saddr; if (res.dev) { iph->saddr = inet_select_addr(res.dev, res.nexthop, RT_SCOPE_LINK); } else { iph->saddr = temp; } iph->ttl = 255; iph->check = 0; iph->check = ip_fast_csum(iph, iph->ihl); echo->type = MPLS_ECHO_REPLY; do_gettimeofday(&tv); echo->t_rcvd[0] = htonl(tv.tv_sec+JAN_1970); echo->t_rcvd[1] = NTPFRAC(tv.tv_usec); temp = udph->source; udph->source = udph->dest; udph->dest = temp; if (MPLS_MODE_DO_NOT_REPLY == echo->mode) { printk("mpls_echo_input -not reply mode drop.\n"); goto drop; } if (MPLS_MODE_IPX_UDP_ALERT == echo->mode) { //Push router alert to ip option. } skb->protocol = htons(ETH_P_IP); if (FIB_MG_TYPE_FTN_BASIC == res.type) { if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel)) { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.glabel, 1); } if (2 == res.count) { if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel2)) { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.glabel2, 0); } } } else { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.label, 1); if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel)) { skb_push_label(skb, 128, res.glabel, 0); } if (3 == res.count) { if (MPLS_IMPLICIT_NULL != MPLS_LABEL(res.glabel2)) { skb->protocol = htons(ETH_P_MPLS_UC) ; skb_push_label(skb, 128, res.glabel2, 0); } } } if (MPLS_MODE_CTRL_CHANNEL == echo->mode) { skb_push_label(skb, 128, 1, 0); } skb->nh.raw = skb->data; skb->dev = res.dev; if (!res.neigh) { res.neigh = __neigh_arp_lookup(&arp_tbl, &res.nexthop, NULL, res.dev, NEIGHBOUR_CREAT); } read_lock_bh(&res.neigh->lock); if (!(res.neigh->nud_state&(NUD_CONNECTED|NUD_DELAY|NUD_PROBE))) { saddr = inet_select_addr(res.dev, res.nexthop, RT_SCOPE_LINK); arp_send(ARPOP_REQUEST, ETH_P_ARP, res.nexthop, res.dev, saddr, res.neigh->ha, res.dev->dev_addr, NULL); read_unlock_bh(&res.neigh->lock); printk("mpls_echo_input -neigh invalid drop.\n"); goto drop; } eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); eth->h_proto = (ETH_P_802_3 != skb->protocol) ? htons(skb->protocol) : htons(skb->len); memcpy(eth->h_source, res.dev->dev_addr, res.dev->addr_len); memcpy(eth->h_dest, res.neigh->ha, res.dev->addr_len); skb->mac.raw = skb->data ; skb->mac_len = ETH_HLEN; read_unlock_bh(&res.neigh->lock); neigh_release(res.neigh); dev_queue_xmit(skb); return 0; drop: kfree_skb(skb); return -1; }
/* Default Router Selection (RFC 2461 6.3.6) */ static struct rt6_info *rt6_best_dflt(struct rt6_info *rt, int oif) { struct rt6_info *match = NULL; struct rt6_info *sprt; int mpri = 0; for (sprt = rt; sprt; sprt = sprt->u.next) { struct neighbour *neigh; int m = 0; if (!oif || (sprt->rt6i_dev && sprt->rt6i_dev->ifindex == oif)) m += 8; if (sprt == rt6_dflt_pointer) m += 4; if ((neigh = sprt->rt6i_nexthop) != NULL) { read_lock_bh(&neigh->lock); switch (neigh->nud_state) { case NUD_REACHABLE: m += 3; break; case NUD_STALE: case NUD_DELAY: case NUD_PROBE: m += 2; break; case NUD_NOARP: case NUD_PERMANENT: m += 1; break; case NUD_INCOMPLETE: default: read_unlock_bh(&neigh->lock); continue; } read_unlock_bh(&neigh->lock); } else { continue; } if (m > mpri || m >= 12) { match = sprt; mpri = m; if (m >= 12) { /* we choose the lastest default router if it * is in (probably) reachable state. * If route changed, we should do pmtu * discovery. --yoshfuji */ break; } } } spin_lock(&rt6_dflt_lock); if (!match) { /* * No default routers are known to be reachable. * SHOULD round robin */ if (rt6_dflt_pointer) { for (sprt = rt6_dflt_pointer->u.next; sprt; sprt = sprt->u.next) { if (sprt->u.dst.obsolete <= 0 && sprt->u.dst.error == 0) { match = sprt; break; } } for (sprt = rt; !match && sprt; sprt = sprt->u.next) { if (sprt->u.dst.obsolete <= 0 && sprt->u.dst.error == 0) { match = sprt; break; } if (sprt == rt6_dflt_pointer) break; } } } if (match) rt6_dflt_pointer = match; spin_unlock(&rt6_dflt_lock); if (!match) { /* * Last Resort: if no default routers found, * use addrconf default route. * We don't record this route. */ for (sprt = ip6_routing_table.leaf; sprt; sprt = sprt->u.next) { if ((sprt->rt6i_flags & RTF_DEFAULT) && (!oif || (sprt->rt6i_dev && sprt->rt6i_dev->ifindex == oif))) { match = sprt; break; } } if (!match) { /* no default route. give up. */ match = &ip6_null_entry; } } return match; }
inline void brk_list_read_unlock(void) { read_unlock_bh(&brk_list_lock); }
int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) { int uninitialized_var(err); struct net *net = sock_net(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct in6_flowlabel_req freq; struct ipv6_fl_socklist *sfl1=NULL; struct ipv6_fl_socklist *sfl, **sflp; struct ip6_flowlabel *fl, *fl1 = NULL; if (optlen < sizeof(freq)) return -EINVAL; if (copy_from_user(&freq, optval, sizeof(freq))) return -EFAULT; switch (freq.flr_action) { case IPV6_FL_A_PUT: write_lock_bh(&ip6_sk_fl_lock); for (sflp = &np->ipv6_fl_list; (sfl=*sflp)!=NULL; sflp = &sfl->next) { if (sfl->fl->label == freq.flr_label) { if (freq.flr_label == (np->flow_label&IPV6_FLOWLABEL_MASK)) np->flow_label &= ~IPV6_FLOWLABEL_MASK; *sflp = sfl->next; write_unlock_bh(&ip6_sk_fl_lock); fl_release(sfl->fl); kfree(sfl); return 0; } } write_unlock_bh(&ip6_sk_fl_lock); return -ESRCH; case IPV6_FL_A_RENEW: read_lock_bh(&ip6_sk_fl_lock); for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) { if (sfl->fl->label == freq.flr_label) { err = fl6_renew(sfl->fl, freq.flr_linger, freq.flr_expires); read_unlock_bh(&ip6_sk_fl_lock); return err; } } read_unlock_bh(&ip6_sk_fl_lock); if (freq.flr_share == IPV6_FL_S_NONE && capable(CAP_NET_ADMIN)) { fl = fl_lookup(net, freq.flr_label); if (fl) { err = fl6_renew(fl, freq.flr_linger, freq.flr_expires); fl_release(fl); return err; } } return -ESRCH; case IPV6_FL_A_GET: if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) return -EINVAL; fl = fl_create(net, sk, &freq, optval, optlen, &err); if (fl == NULL) return err; sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); if (freq.flr_label) { err = -EEXIST; read_lock_bh(&ip6_sk_fl_lock); for (sfl = np->ipv6_fl_list; sfl; sfl = sfl->next) { if (sfl->fl->label == freq.flr_label) { if (freq.flr_flags&IPV6_FL_F_EXCL) { read_unlock_bh(&ip6_sk_fl_lock); goto done; } fl1 = sfl->fl; atomic_inc(&fl1->users); break; } } read_unlock_bh(&ip6_sk_fl_lock); if (fl1 == NULL) fl1 = fl_lookup(net, freq.flr_label); if (fl1) { recheck: err = -EEXIST; if (freq.flr_flags&IPV6_FL_F_EXCL) goto release; err = -EPERM; if (fl1->share == IPV6_FL_S_EXCL || fl1->share != fl->share || fl1->owner != fl->owner) goto release; err = -EINVAL; if (!ipv6_addr_equal(&fl1->dst, &fl->dst) || ipv6_opt_cmp(fl1->opt, fl->opt)) goto release; err = -ENOMEM; if (sfl1 == NULL) goto release; if (fl->linger > fl1->linger) fl1->linger = fl->linger; if ((long)(fl->expires - fl1->expires) > 0) fl1->expires = fl->expires; fl_link(np, sfl1, fl1); fl_free(fl); return 0; release: fl_release(fl1); goto done; } } err = -ENOENT; if (!(freq.flr_flags&IPV6_FL_F_CREATE)) goto done; err = -ENOMEM; if (sfl1 == NULL || (err = mem_check(sk)) != 0) goto done; fl1 = fl_intern(net, fl, freq.flr_label); if (fl1 != NULL) goto recheck; if (!freq.flr_label) { if (copy_to_user(&((struct in6_flowlabel_req __user *) optval)->flr_label, &fl->label, sizeof(fl->label))) { /* Intentionally ignore fault. */ } } fl_link(np, sfl1, fl); return 0; default: return -EINVAL; } done: fl_free(fl); kfree(sfl1); return err; }
/* One level of recursion won't kill us */ static void dump_packet(const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int iphoff) { struct iphdr _iph; const struct iphdr *ih; unsigned int logflags; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; else logflags = NF_LOG_MASK; ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); if (ih == NULL) { printk("TRUNCATED"); return; } /* Important fields: * 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=%pI4 DST=%pI4 ", &ih->saddr, &ih->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 ", ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); /* Max length: 6 "CE DF MF " */ if (ntohs(ih->frag_off) & IP_CE) printk("CE "); if (ntohs(ih->frag_off) & IP_DF) printk("DF "); if (ntohs(ih->frag_off) & IP_MF) printk("MF "); /* Max length: 11 "FRAG:65535 " */ if (ntohs(ih->frag_off) & IP_OFFSET) printk("FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); if ((logflags & IPT_LOG_IPOPT) && ih->ihl * 4 > sizeof(struct iphdr)) { const unsigned char *op; unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; unsigned int i, optsize; optsize = ih->ihl * 4 - sizeof(struct iphdr); op = skb_header_pointer(skb, iphoff+sizeof(_iph), optsize, _opt); if (op == NULL) { printk("TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ printk("OPT ("); for (i = 0; i < optsize; i++) printk("%02X", op[i]); printk(") "); } switch (ih->protocol) { case IPPROTO_TCP: { struct tcphdr _tcph; const struct tcphdr *th; /* Max length: 10 "PROTO=TCP " */ printk("PROTO=TCP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ th = skb_header_pointer(skb, iphoff + ih->ihl * 4, sizeof(_tcph), &_tcph); if (th == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 20 "SPT=65535 DPT=65535 " */ printk("SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ if (logflags & IPT_LOG_TCPSEQ) printk("SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); /* Max length: 13 "WINDOW=65535 " */ printk("WINDOW=%u ", ntohs(th->window)); /* Max length: 9 "RES=0x3F " */ printk("RES=0x%02x ", (u8)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ if (th->cwr) printk("CWR "); if (th->ece) printk("ECE "); if (th->urg) printk("URG "); if (th->ack) printk("ACK "); if (th->psh) printk("PSH "); if (th->rst) printk("RST "); if (th->syn) printk("SYN "); if (th->fin) printk("FIN "); /* Max length: 11 "URGP=65535 " */ printk("URGP=%u ", ntohs(th->urg_ptr)); if ((logflags & IPT_LOG_TCPOPT) && th->doff * 4 > sizeof(struct tcphdr)) { unsigned char _opt[4 * 15 - sizeof(struct tcphdr)]; const unsigned char *op; unsigned int i, optsize; optsize = th->doff * 4 - sizeof(struct tcphdr); op = skb_header_pointer(skb, iphoff+ih->ihl*4+sizeof(_tcph), optsize, _opt); if (op == NULL) { printk("TRUNCATED"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ printk("OPT ("); for (i = 0; i < optsize; i++) printk("%02X", op[i]); printk(") "); } break; } case IPPROTO_UDP: case IPPROTO_UDPLITE: { struct udphdr _udph; const struct udphdr *uh; if (ih->protocol == IPPROTO_UDP) /* Max length: 10 "PROTO=UDP " */ printk("PROTO=UDP " ); else /* Max length: 14 "PROTO=UDPLITE " */ printk("PROTO=UDPLITE "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ uh = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_udph), &_udph); if (uh == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 20 "SPT=65535 DPT=65535 " */ printk("SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); break; } case IPPROTO_ICMP: { struct icmphdr _icmph; const struct icmphdr *ich; static const size_t required_len[NR_ICMP_TYPES+1] = { [ICMP_ECHOREPLY] = 4, [ICMP_DEST_UNREACH] = 8 + sizeof(struct iphdr), [ICMP_SOURCE_QUENCH] = 8 + sizeof(struct iphdr), [ICMP_REDIRECT] = 8 + sizeof(struct iphdr), [ICMP_ECHO] = 4, [ICMP_TIME_EXCEEDED] = 8 + sizeof(struct iphdr), [ICMP_PARAMETERPROB] = 8 + sizeof(struct iphdr), [ICMP_TIMESTAMP] = 20, [ICMP_TIMESTAMPREPLY] = 20, [ICMP_ADDRESS] = 12, [ICMP_ADDRESSREPLY] = 12 }; /* Max length: 11 "PROTO=ICMP " */ printk("PROTO=ICMP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, sizeof(_icmph), &_icmph); if (ich == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Max length: 18 "TYPE=255 CODE=255 " */ printk("TYPE=%u CODE=%u ", ich->type, ich->code); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ if (ich->type <= NR_ICMP_TYPES && required_len[ich->type] && skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { printk("INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } switch (ich->type) { case ICMP_ECHOREPLY: case ICMP_ECHO: /* Max length: 19 "ID=65535 SEQ=65535 " */ printk("ID=%u SEQ=%u ", ntohs(ich->un.echo.id), ntohs(ich->un.echo.sequence)); break; case ICMP_PARAMETERPROB: /* Max length: 14 "PARAMETER=255 " */ printk("PARAMETER=%u ", ntohl(ich->un.gateway) >> 24); break; case ICMP_REDIRECT: /* Max length: 24 "GATEWAY=255.255.255.255 " */ printk("GATEWAY=%pI4 ", &ich->un.gateway); /* Fall through */ case ICMP_DEST_UNREACH: case ICMP_SOURCE_QUENCH: case ICMP_TIME_EXCEEDED: /* Max length: 3+maxlen */ if (!iphoff) { /* Only recurse once. */ printk("["); dump_packet(info, skb, iphoff + ih->ihl*4+sizeof(_icmph)); printk("] "); } /* Max length: 10 "MTU=65535 " */ if (ich->type == ICMP_DEST_UNREACH && ich->code == ICMP_FRAG_NEEDED) printk("MTU=%u ", ntohs(ich->un.frag.mtu)); } break; } /* Max Length */ case IPPROTO_AH: { struct ip_auth_hdr _ahdr; const struct ip_auth_hdr *ah; if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 9 "PROTO=AH " */ printk("PROTO=AH "); /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ah = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_ahdr), &_ahdr); if (ah == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ printk("SPI=0x%x ", ntohl(ah->spi)); break; } case IPPROTO_ESP: { struct ip_esp_hdr _esph; const struct ip_esp_hdr *eh; /* Max length: 10 "PROTO=ESP " */ printk("PROTO=ESP "); if (ntohs(ih->frag_off) & IP_OFFSET) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ eh = skb_header_pointer(skb, iphoff+ih->ihl*4, sizeof(_esph), &_esph); if (eh == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - iphoff - ih->ihl*4); break; } /* Length: 15 "SPI=0xF1234567 " */ printk("SPI=0x%x ", ntohl(eh->spi)); break; } /* Max length: 10 "PROTO 255 " */ default: printk("PROTO=%u ", ih->protocol); } /* Max length: 15 "UID=4294967295 " */ if ((logflags & IPT_LOG_UID) && !iphoff && skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) printk("UID=%u GID=%u ", skb->sk->sk_socket->file->f_cred->fsuid, skb->sk->sk_socket->file->f_cred->fsgid); read_unlock_bh(&skb->sk->sk_callback_lock); } /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!iphoff && skb->mark) printk("MARK=0x%x ", skb->mark); /* Proto Max log string length */ /* IP: 40+46+6+11+127 = 230 */ /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ /* UDP: 10+max(25,20) = 35 */ /* UDPLITE: 14+max(25,20) = 39 */ /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ /* ESP: 10+max(25)+15 = 50 */ /* AH: 9+max(25)+15 = 49 */ /* unknown: 10 */ /* (ICMP allows recursion one level deep) */ /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */ /* maxlen = 230+ 91 + 230 + 252 = 803 */ }
/* This is an inline function, we don't really care about a long * list of arguments */ static inline int __build_packet_message(struct nfnl_log_net *log, struct nfulnl_instance *inst, const struct sk_buff *skb, unsigned int data_len, u_int8_t pf, unsigned int hooknum, const struct net_device *indev, const struct net_device *outdev, const char *prefix, unsigned int plen, const struct nfnl_ct_hook *nfnl_ct, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; sk_buff_data_t old_tail = inst->skb->tail; struct sock *sk; const unsigned char *hwhdrp; nlh = nlmsg_put(inst->skb, 0, 0, nfnl_msg_type(NFNL_SUBSYS_ULOG, NFULNL_MSG_PACKET), sizeof(struct nfgenmsg), 0); if (!nlh) return -1; nfmsg = nlmsg_data(nlh); nfmsg->nfgen_family = pf; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(inst->group_num); memset(&pmsg, 0, sizeof(pmsg)); pmsg.hw_protocol = skb->protocol; pmsg.hook = hooknum; if (nla_put(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg)) goto nla_put_failure; if (prefix && nla_put(inst->skb, NFULA_PREFIX, plen, prefix)) goto nla_put_failure; if (indev) { #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex))) goto nla_put_failure; #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(indev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_thresh or * nf_log_packet. */ nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(br_port_get_rcu(indev)->br->dev->ifindex))) goto nla_put_failure; } else { struct net_device *physindev; /* Case 2: indev is bridge group, we need to look for * physical device (when called from ipv4) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex))) goto nla_put_failure; physindev = nf_bridge_get_physindev(skb); if (physindev && nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(physindev->ifindex))) goto nla_put_failure; } #endif } if (outdev) { #if !IS_ENABLED(CONFIG_BRIDGE_NETFILTER) if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) goto nla_put_failure; #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(outdev->ifindex)) || /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_thresh or * nf_log_packet. */ nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(br_port_get_rcu(outdev)->br->dev->ifindex))) goto nla_put_failure; } else { struct net_device *physoutdev; /* Case 2: indev is a bridge group, we need to look * for physical device (when called from ipv4) */ if (nla_put_be32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex))) goto nla_put_failure; physoutdev = nf_bridge_get_physoutdev(skb); if (physoutdev && nla_put_be32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(physoutdev->ifindex))) goto nla_put_failure; } #endif } if (skb->mark && nla_put_be32(inst->skb, NFULA_MARK, htonl(skb->mark))) goto nla_put_failure; if (indev && skb->dev && skb->mac_header != skb->network_header) { struct nfulnl_msg_packet_hw phw; int len; memset(&phw, 0, sizeof(phw)); len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { phw.hw_addrlen = htons(len); if (nla_put(inst->skb, NFULA_HWADDR, sizeof(phw), &phw)) goto nla_put_failure; } } if (indev && skb_mac_header_was_set(skb)) { if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || nla_put_be16(inst->skb, NFULA_HWLEN, htons(skb->dev->hard_header_len))) goto nla_put_failure; hwhdrp = skb_mac_header(skb); if (skb->dev->type == ARPHRD_SIT) hwhdrp -= ETH_HLEN; if (hwhdrp >= skb->head && nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, hwhdrp)) goto nla_put_failure; } if (skb->tstamp) { struct nfulnl_msg_packet_timestamp ts; struct timespec64 kts = ktime_to_timespec64(skb->tstamp); ts.sec = cpu_to_be64(kts.tv_sec); ts.usec = cpu_to_be64(kts.tv_nsec / NSEC_PER_USEC); if (nla_put(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts)) goto nla_put_failure; } /* UID */ sk = skb->sk; if (sk && sk_fullsock(sk)) { read_lock_bh(&sk->sk_callback_lock); if (sk->sk_socket && sk->sk_socket->file) { struct file *file = sk->sk_socket->file; const struct cred *cred = file->f_cred; struct user_namespace *user_ns = inst->peer_user_ns; __be32 uid = htonl(from_kuid_munged(user_ns, cred->fsuid)); __be32 gid = htonl(from_kgid_munged(user_ns, cred->fsgid)); read_unlock_bh(&sk->sk_callback_lock); if (nla_put_be32(inst->skb, NFULA_UID, uid) || nla_put_be32(inst->skb, NFULA_GID, gid)) goto nla_put_failure; } else read_unlock_bh(&sk->sk_callback_lock); } /* local sequence number */ if ((inst->flags & NFULNL_CFG_F_SEQ) && nla_put_be32(inst->skb, NFULA_SEQ, htonl(inst->seq++))) goto nla_put_failure; /* global sequence number */ if ((inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) && nla_put_be32(inst->skb, NFULA_SEQ_GLOBAL, htonl(atomic_inc_return(&log->global_seq)))) goto nla_put_failure; if (ct && nfnl_ct->build(inst->skb, ct, ctinfo, NFULA_CT, NFULA_CT_INFO) < 0) goto nla_put_failure; if (data_len) { struct nlattr *nla; int size = nla_attr_size(data_len); if (skb_tailroom(inst->skb) < nla_total_size(data_len)) goto nla_put_failure; nla = skb_put(inst->skb, nla_total_size(data_len)); nla->nla_type = NFULA_PAYLOAD; nla->nla_len = size; if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) BUG(); } nlh->nlmsg_len = inst->skb->tail - old_tail; return 0; nla_put_failure: PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n"); return -1; }
static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg) { switch (cmd & 0xff) { case 12: /* SIOCSIFADDR */ return compat_sys_ioctl(fd, SIOCSIFADDR, arg); case 13: /* SIOCGIFADDR */ return compat_sys_ioctl(fd, SIOCGIFADDR, arg); case 14: /* SIOCSIFDSTADDR */ return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); case 15: /* SIOCGIFDSTADDR */ return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); case 16: /* SIOCSIFFLAGS */ return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); case 17: /* SIOCGIFFLAGS */ return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); case 18: /* SIOCSIFMEM */ return compat_sys_ioctl(fd, SIOCSIFMEM, arg); case 19: /* SIOCGIFMEM */ return compat_sys_ioctl(fd, SIOCGIFMEM, arg); case 20: /* SIOCGIFCONF */ return compat_sys_ioctl(fd, SIOCGIFCONF, arg); case 21: /* SIOCSIFMTU */ return compat_sys_ioctl(fd, SIOCSIFMTU, arg); case 22: /* SIOCGIFMTU */ return compat_sys_ioctl(fd, SIOCGIFMTU, arg); case 23: /* SIOCGIFBRDADDR */ return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); case 24: /* SIOCSIFBRDADDR */ return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); case 25: /* SIOCGIFNETMASK */ return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); case 26: /* SIOCSIFNETMASK */ return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); case 27: /* SIOCGIFMETRIC */ return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); case 28: /* SIOCSIFMETRIC */ return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); case 30: /* SIOCSARP */ return compat_sys_ioctl(fd, SIOCSARP, arg); case 31: /* SIOCGARP */ return compat_sys_ioctl(fd, SIOCGARP, arg); case 32: /* SIOCDARP */ return compat_sys_ioctl(fd, SIOCDARP, arg); case 52: /* SIOCGETNAME */ case 53: /* SIOCGETPEER */ { struct sockaddr uaddr; int uaddr_len = sizeof(struct sockaddr), ret; long args[3]; mm_segment_t old_fs = get_fs(); int (*sys_socketcall)(int, unsigned long *) = (int (*)(int, unsigned long *))SYS(socketcall); args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len; set_fs(KERNEL_DS); ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME, args); set_fs(old_fs); if (ret >= 0) { if (copy_to_user((char *)A(arg), &uaddr, uaddr_len)) return -EFAULT; } return ret; } #if 0 case 86: /* SIOCSOCKSYS */ return socksys_syscall(fd, arg); #endif case 87: /* SIOCGIFNUM */ { struct net_device *d; int i = 0; read_lock_bh(&dev_base_lock); for (d = dev_base; d; d = d->next) i++; read_unlock_bh(&dev_base_lock); if (put_user (i, (int *)A(arg))) return -EFAULT; return 0; } } return -ENOSYS; }
/* This is an inline function, we don't really care about a long * list of arguments */ static inline int __build_packet_message(struct nfulnl_instance *inst, const struct sk_buff *skb, unsigned int data_len, u_int8_t pf, unsigned int hooknum, const struct net_device *indev, const struct net_device *outdev, const char *prefix, unsigned int plen) { struct nfulnl_msg_packet_hdr pmsg; struct nlmsghdr *nlh; struct nfgenmsg *nfmsg; sk_buff_data_t old_tail = inst->skb->tail; nlh = NLMSG_PUT(inst->skb, 0, 0, NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET, sizeof(struct nfgenmsg)); nfmsg = NLMSG_DATA(nlh); nfmsg->nfgen_family = pf; nfmsg->version = NFNETLINK_V0; nfmsg->res_id = htons(inst->group_num); pmsg.hw_protocol = skb->protocol; pmsg.hook = hooknum; NLA_PUT(inst->skb, NFULA_PACKET_HDR, sizeof(pmsg), &pmsg); if (prefix) NLA_PUT(inst->skb, NFULA_PREFIX, plen, prefix); if (indev) { #ifndef CONFIG_BRIDGE_NETFILTER NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex)); #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical input device, we need to * look for bridge group (when called from * netfilter_bridge) */ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(indev->ifindex)); /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, htonl(br_port_get_rcu(indev)->br->dev->ifindex)); } else { /* Case 2: indev is bridge group, we need to look for * physical device (when called from ipv4) */ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_INDEV, htonl(indev->ifindex)); if (skb->nf_bridge && skb->nf_bridge->physindev) NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSINDEV, htonl(skb->nf_bridge->physindev->ifindex)); } #endif } if (outdev) { #ifndef CONFIG_BRIDGE_NETFILTER NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex)); #else if (pf == PF_BRIDGE) { /* Case 1: outdev is physical output device, we need to * look for bridge group (when called from * netfilter_bridge) */ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(outdev->ifindex)); /* this is the bridge group "brX" */ /* rcu_read_lock()ed by nf_hook_slow or nf_log_packet */ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(br_port_get_rcu(outdev)->br->dev->ifindex)); } else { /* Case 2: indev is a bridge group, we need to look * for physical device (when called from ipv4) */ NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, htonl(outdev->ifindex)); if (skb->nf_bridge && skb->nf_bridge->physoutdev) NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_PHYSOUTDEV, htonl(skb->nf_bridge->physoutdev->ifindex)); } #endif } if (skb->mark) NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark)); if (indev && skb->dev && skb->mac_header != skb->network_header) { struct nfulnl_msg_packet_hw phw; int len = dev_parse_header(skb, phw.hw_addr); if (len > 0) { phw.hw_addrlen = htons(len); NLA_PUT(inst->skb, NFULA_HWADDR, sizeof(phw), &phw); } } if (indev && skb_mac_header_was_set(skb)) { NLA_PUT_BE16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)); NLA_PUT_BE16(inst->skb, NFULA_HWLEN, htons(skb->dev->hard_header_len)); NLA_PUT(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, skb_mac_header(skb)); } if (skb->tstamp.tv64) { struct nfulnl_msg_packet_timestamp ts; struct timeval tv = ktime_to_timeval(skb->tstamp); ts.sec = cpu_to_be64(tv.tv_sec); ts.usec = cpu_to_be64(tv.tv_usec); NLA_PUT(inst->skb, NFULA_TIMESTAMP, sizeof(ts), &ts); } /* UID */ if (skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) { struct file *file = skb->sk->sk_socket->file; __be32 uid = htonl(file->f_cred->fsuid); __be32 gid = htonl(file->f_cred->fsgid); /* need to unlock here since NLA_PUT may goto */ read_unlock_bh(&skb->sk->sk_callback_lock); NLA_PUT_BE32(inst->skb, NFULA_UID, uid); NLA_PUT_BE32(inst->skb, NFULA_GID, gid); } else read_unlock_bh(&skb->sk->sk_callback_lock); } /* local sequence number */ if (inst->flags & NFULNL_CFG_F_SEQ) NLA_PUT_BE32(inst->skb, NFULA_SEQ, htonl(inst->seq++)); /* global sequence number */ if (inst->flags & NFULNL_CFG_F_SEQ_GLOBAL) NLA_PUT_BE32(inst->skb, NFULA_SEQ_GLOBAL, htonl(atomic_inc_return(&global_seq))); if (data_len) { struct nlattr *nla; int size = nla_attr_size(data_len); if (skb_tailroom(inst->skb) < nla_total_size(data_len)) { printk(KERN_WARNING "nfnetlink_log: no tailroom!\n"); goto nlmsg_failure; } nla = (struct nlattr *)skb_put(inst->skb, nla_total_size(data_len)); nla->nla_type = NFULA_PAYLOAD; nla->nla_len = size; if (skb_copy_bits(skb, 0, nla_data(nla), data_len)) BUG(); } nlh->nlmsg_len = inst->skb->tail - old_tail; return 0; nlmsg_failure: nla_put_failure: PRINTR(KERN_ERR "nfnetlink_log: error creating log nlmsg\n"); return -1; }
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) { __be32 saddr = 0; u8 *dst_ha = NULL; struct net_device *dev = neigh->dev; __be32 target = *(__be32 *)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev; #ifdef CONFIG_HTC_NETWORK_CNE __be32 dev_addr = 0; dev_addr = inet_select_addr(dev, target, RT_SCOPE_LINK); #endif rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) { rcu_read_unlock(); return; } switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) saddr = ip_hdr(skb)->saddr; break; case 1: if (!skb) break; saddr = ip_hdr(skb)->saddr; if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) { if (inet_addr_onlink(in_dev, target, saddr)) break; } saddr = 0; break; case 2: break; } rcu_read_unlock(); if (!saddr) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); probes -= neigh->parms->ucast_probes; if (probes < 0) { if (!(neigh->nud_state & NUD_VALID)) printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); dst_ha = neigh->ha; read_lock_bh(&neigh->lock); } else { probes -= neigh->parms->app_probes; if (probes < 0) { #ifdef CONFIG_ARPD neigh_app_ns(neigh); #endif return; } } #ifdef CONFIG_HTC_NETWORK_CNE if (dev_addr != saddr) { printk(KERN_DEBUG "CnE detects wrong sender IP in ARP\n"); saddr = dev_addr; } #endif arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_ha, dev->dev_addr, NULL); if (dst_ha) read_unlock_bh(&neigh->lock); }
static int ip_masq_user_info(char *buffer, char **start, off_t offset, int length, int proto) { off_t pos=0, begin; struct ip_masq *ms; char temp[129]; int idx = 0; int len=0; int magic_control; MOD_INC_USE_COUNT; IP_MASQ_DEBUG(1-debug, "Entered user_info with proto=%d\n", proto); if (offset < 128) { sprintf(temp, "Prot SrcIP SPrt DstIP DPrt MAddr MPrt State Flgs Ref Ctl Expires (free=%d,%d,%d)", atomic_read(ip_masq_free_ports), atomic_read(ip_masq_free_ports+1), atomic_read(ip_masq_free_ports+2)); len = sprintf(buffer, "%-127s\n", temp); } pos = 128; for(idx = 0; idx < IP_MASQ_TAB_SIZE; idx++) { /* * Lock is actually only need in next loop * we are called from uspace: must stop bh. */ read_lock_bh(&__ip_masq_lock); for(ms = ip_masq_m_tab[idx]; ms ; ms = ms->m_link) { if (ms->protocol != proto) { continue; } pos += 128; if (pos <= offset) { len = 0; continue; } /* * We have locked the tables, no need to del/add timers * nor cli() 8) */ magic_control = atomic_read(&ms->n_control); if (!magic_control && ms->control) magic_control = -1; sprintf(temp,"%-4s %08lX:%04X %08lX:%04X %08lX:%04X %-12s %3X %4d %3d %7lu", masq_proto_name(ms->protocol), ntohl(ms->saddr), ntohs(ms->sport), ntohl(ms->daddr), ntohs(ms->dport), ntohl(ms->maddr), ntohs(ms->mport), ip_masq_state_name(ms->state), ms->flags, atomic_read(&ms->refcnt), magic_control, (ms->timer.expires-jiffies)/HZ); len += sprintf(buffer+len, "%-127s\n", temp); if(len >= length) { read_unlock_bh(&__ip_masq_lock); goto done; } } read_unlock_bh(&__ip_masq_lock); } done: if (len) { begin = len - (pos - offset); *start = buffer + begin; len -= begin; } if(len>length) len = length; MOD_DEC_USE_COUNT; return len; }
static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) { __be32 saddr = 0; u8 *dst_ha = NULL; struct net_device *dev = neigh->dev; __be32 target = *(__be32 *)neigh->primary_key; int probes = atomic_read(&neigh->probes); struct in_device *in_dev; rcu_read_lock(); in_dev = __in_dev_get_rcu(dev); if (!in_dev) { rcu_read_unlock(); return; } switch (IN_DEV_ARP_ANNOUNCE(in_dev)) { default: case 0: /* By default announce any local IP */ if (skb && inet_addr_type(dev_net(dev), ip_hdr(skb)->saddr) == RTN_LOCAL) saddr = ip_hdr(skb)->saddr; break; case 1: /* Restrict announcements of saddr in same subnet */ if (!skb) break; saddr = ip_hdr(skb)->saddr; if (inet_addr_type(dev_net(dev), saddr) == RTN_LOCAL) { /* saddr should be known to target */ if (inet_addr_onlink(in_dev, target, saddr)) break; } saddr = 0; break; case 2: /* Avoid secondary IPs, get a primary/preferred one */ break; } rcu_read_unlock(); if (!saddr) saddr = inet_select_addr(dev, target, RT_SCOPE_LINK); probes -= neigh->parms->ucast_probes; if (probes < 0) { if (!(neigh->nud_state & NUD_VALID)) printk(KERN_DEBUG "trying to ucast probe in NUD_INVALID\n"); dst_ha = neigh->ha; read_lock_bh(&neigh->lock); } else { probes -= neigh->parms->app_probes; if (probes < 0) { #ifdef CONFIG_ARPD neigh_app_ns(neigh); #endif return; } } arp_send(ARPOP_REQUEST, ETH_P_ARP, target, dev, saddr, dst_ha, dev->dev_addr, NULL); if (dst_ha) read_unlock_bh(&neigh->lock); }
/* One level of recursion won't kill us */ static void dump_packet(const struct nf_loginfo *info, const struct sk_buff *skb, unsigned int ip6hoff, int recurse) { u_int8_t currenthdr; int fragment; struct ipv6hdr _ip6h; const struct ipv6hdr *ih; unsigned int ptr; unsigned int hdrlen = 0; unsigned int logflags; if (info->type == NF_LOG_TYPE_LOG) logflags = info->u.log.logflags; else logflags = NF_LOG_MASK; ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); if (ih == NULL) { printk("TRUNCATED"); return; } /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ printk("SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ printk("LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", ntohs(ih->payload_len) + sizeof(struct ipv6hdr), (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, ih->hop_limit, (ntohl(*(__be32 *)ih) & 0x000fffff)); fragment = 0; ptr = ip6hoff + sizeof(struct ipv6hdr); currenthdr = ih->nexthdr; while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { struct ipv6_opt_hdr _hdr; const struct ipv6_opt_hdr *hp; hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); if (hp == NULL) { printk("TRUNCATED"); return; } /* Max length: 48 "OPT (...) " */ if (logflags & IP6T_LOG_IPOPT) printk("OPT ( "); switch (currenthdr) { case IPPROTO_FRAGMENT: { struct frag_hdr _fhdr; const struct frag_hdr *fh; printk("FRAG:"); fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), &_fhdr); if (fh == NULL) { printk("TRUNCATED "); return; } /* Max length: 6 "65535 " */ printk("%u ", ntohs(fh->frag_off) & 0xFFF8); /* Max length: 11 "INCOMPLETE " */ if (fh->frag_off & htons(0x0001)) printk("INCOMPLETE "); printk("ID:%08x ", ntohl(fh->identification)); if (ntohs(fh->frag_off) & 0xFFF8) fragment = 1; hdrlen = 8; break; } case IPPROTO_DSTOPTS: case IPPROTO_ROUTING: case IPPROTO_HOPOPTS: if (fragment) { if (logflags & IP6T_LOG_IPOPT) printk(")"); return; } hdrlen = ipv6_optlen(hp); break; /* Max Length */ case IPPROTO_AH: if (logflags & IP6T_LOG_IPOPT) { struct ip_auth_hdr _ahdr; const struct ip_auth_hdr *ah; /* Max length: 3 "AH " */ printk("AH "); if (fragment) { printk(")"); return; } ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), &_ahdr); if (ah == NULL) { /* * Max length: 26 "INCOMPLETE [65535 * bytes] )" */ printk("INCOMPLETE [%u bytes] )", skb->len - ptr); return; } /* Length: 15 "SPI=0xF1234567 */ printk("SPI=0x%x ", ntohl(ah->spi)); } hdrlen = (hp->hdrlen+2)<<2; break; case IPPROTO_ESP: if (logflags & IP6T_LOG_IPOPT) { struct ip_esp_hdr _esph; const struct ip_esp_hdr *eh; /* Max length: 4 "ESP " */ printk("ESP "); if (fragment) { printk(")"); return; } /* * Max length: 26 "INCOMPLETE [65535 bytes] )" */ eh = skb_header_pointer(skb, ptr, sizeof(_esph), &_esph); if (eh == NULL) { printk("INCOMPLETE [%u bytes] )", skb->len - ptr); return; } /* Length: 16 "SPI=0xF1234567 )" */ printk("SPI=0x%x )", ntohl(eh->spi) ); } return; default: /* Max length: 20 "Unknown Ext Hdr 255" */ printk("Unknown Ext Hdr %u", currenthdr); return; } if (logflags & IP6T_LOG_IPOPT) printk(") "); currenthdr = hp->nexthdr; ptr += hdrlen; } switch (currenthdr) { case IPPROTO_TCP: { struct tcphdr _tcph; const struct tcphdr *th; /* Max length: 10 "PROTO=TCP " */ printk("PROTO=TCP "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ th = skb_header_pointer(skb, ptr, sizeof(_tcph), &_tcph); if (th == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 20 "SPT=65535 DPT=65535 " */ printk("SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ if (logflags & IP6T_LOG_TCPSEQ) printk("SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); /* Max length: 13 "WINDOW=65535 " */ printk("WINDOW=%u ", ntohs(th->window)); /* Max length: 9 "RES=0x3C " */ printk("RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & TCP_RESERVED_BITS) >> 22)); /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ if (th->cwr) printk("CWR "); if (th->ece) printk("ECE "); if (th->urg) printk("URG "); if (th->ack) printk("ACK "); if (th->psh) printk("PSH "); if (th->rst) printk("RST "); if (th->syn) printk("SYN "); if (th->fin) printk("FIN "); /* Max length: 11 "URGP=65535 " */ printk("URGP=%u ", ntohs(th->urg_ptr)); if ((logflags & IP6T_LOG_TCPOPT) && th->doff * 4 > sizeof(struct tcphdr)) { u_int8_t _opt[60 - sizeof(struct tcphdr)]; const u_int8_t *op; unsigned int i; unsigned int optsize = th->doff * 4 - sizeof(struct tcphdr); op = skb_header_pointer(skb, ptr + sizeof(struct tcphdr), optsize, _opt); if (op == NULL) { printk("OPT (TRUNCATED)"); return; } /* Max length: 127 "OPT (" 15*4*2chars ") " */ printk("OPT ("); for (i =0; i < optsize; i++) printk("%02X", op[i]); printk(") "); } break; } case IPPROTO_UDP: case IPPROTO_UDPLITE: { struct udphdr _udph; const struct udphdr *uh; if (currenthdr == IPPROTO_UDP) /* Max length: 10 "PROTO=UDP " */ printk("PROTO=UDP " ); else /* Max length: 14 "PROTO=UDPLITE " */ printk("PROTO=UDPLITE "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ uh = skb_header_pointer(skb, ptr, sizeof(_udph), &_udph); if (uh == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 20 "SPT=65535 DPT=65535 " */ printk("SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); break; } case IPPROTO_ICMPV6: { struct icmp6hdr _icmp6h; const struct icmp6hdr *ic; /* Max length: 13 "PROTO=ICMPv6 " */ printk("PROTO=ICMPv6 "); if (fragment) break; /* Max length: 25 "INCOMPLETE [65535 bytes] " */ ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); if (ic == NULL) { printk("INCOMPLETE [%u bytes] ", skb->len - ptr); return; } /* Max length: 18 "TYPE=255 CODE=255 " */ printk("TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); switch (ic->icmp6_type) { case ICMPV6_ECHO_REQUEST: case ICMPV6_ECHO_REPLY: /* Max length: 19 "ID=65535 SEQ=65535 " */ printk("ID=%u SEQ=%u ", ntohs(ic->icmp6_identifier), ntohs(ic->icmp6_sequence)); break; case ICMPV6_MGM_QUERY: case ICMPV6_MGM_REPORT: case ICMPV6_MGM_REDUCTION: break; case ICMPV6_PARAMPROB: /* Max length: 17 "POINTER=ffffffff " */ printk("POINTER=%08x ", ntohl(ic->icmp6_pointer)); /* Fall through */ case ICMPV6_DEST_UNREACH: case ICMPV6_PKT_TOOBIG: case ICMPV6_TIME_EXCEED: /* Max length: 3+maxlen */ if (recurse) { printk("["); dump_packet(info, skb, ptr + sizeof(_icmp6h), 0); printk("] "); } /* Max length: 10 "MTU=65535 " */ if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) printk("MTU=%u ", ntohl(ic->icmp6_mtu)); } break; } /* Max length: 10 "PROTO=255 " */ default: printk("PROTO=%u ", currenthdr); } /* Max length: 15 "UID=4294967295 " */ if ((logflags & IP6T_LOG_UID) && recurse && skb->sk) { read_lock_bh(&skb->sk->sk_callback_lock); if (skb->sk->sk_socket && skb->sk->sk_socket->file) printk("UID=%u GID=%u ", skb->sk->sk_socket->file->f_cred->fsuid, skb->sk->sk_socket->file->f_cred->fsgid); read_unlock_bh(&skb->sk->sk_callback_lock); } /* Max length: 16 "MARK=0xFFFFFFFF " */ if (!recurse && skb->mark) printk("MARK=0x%x ", skb->mark); }
void ip6_route_input(struct sk_buff *skb) { struct fib6_node *fn; struct rt6_info *rt; int strict; int attempts = 3; strict = ipv6_addr_type(&skb->nh.ipv6h->daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); relookup: read_lock_bh(&rt6_lock); fn = fib6_lookup(&ip6_routing_table, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr); restart: rt = fn->leaf; if ((rt->rt6i_flags & RTF_CACHE)) { if (ip6_rt_policy == 0) { rt = rt6_device_match(rt, skb->dev->ifindex, strict); BACKTRACK(); dst_hold(&rt->u.dst); goto out; } #ifdef CONFIG_RT6_POLICY if ((rt->rt6i_flags & RTF_FLOW)) { struct rt6_info *sprt; for (sprt = rt; sprt; sprt = sprt->u.next) { if (rt6_flow_match_in(sprt, skb)) { rt = sprt; dst_hold(&rt->u.dst); goto out; } } } #endif } rt = rt6_device_match(rt, skb->dev->ifindex, 0); BACKTRACK(); if (ip6_rt_policy == 0) { if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { read_unlock_bh(&rt6_lock); rt = rt6_cow(rt, &skb->nh.ipv6h->daddr, &skb->nh.ipv6h->saddr); if (rt->u.dst.error != -EEXIST || --attempts <= 0) goto out2; /* Race condition! In the gap, when rt6_lock was released someone could insert this route. Relookup. */ goto relookup; } dst_hold(&rt->u.dst); } else { #ifdef CONFIG_RT6_POLICY rt = rt6_flow_lookup_in(rt, skb); #else /* NEVER REACHED */ #endif } out: read_unlock_bh(&rt6_lock); out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; skb->dst = (struct dst_entry *) rt; }
struct dst_entry * ip6_route_output(struct sock *sk, struct flowi *fl) { struct fib6_node *fn; struct rt6_info *rt; int strict; int attempts = 3; strict = ipv6_addr_type(fl->nl_u.ip6_u.daddr) & (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL); relookup: read_lock_bh(&rt6_lock); fn = fib6_lookup(&ip6_routing_table, fl->nl_u.ip6_u.daddr, fl->nl_u.ip6_u.saddr); restart: rt = fn->leaf; if ((rt->rt6i_flags & RTF_CACHE)) { if (ip6_rt_policy == 0) { rt = rt6_device_match(rt, fl->oif, strict); BACKTRACK(); dst_hold(&rt->u.dst); goto out; } #ifdef CONFIG_RT6_POLICY if ((rt->rt6i_flags & RTF_FLOW)) { struct rt6_info *sprt; for (sprt = rt; sprt; sprt = sprt->u.next) { if (rt6_flow_match_out(sprt, sk)) { rt = sprt; dst_hold(&rt->u.dst); goto out; } } } #endif } if (rt->rt6i_flags & RTF_DEFAULT) { if (rt->rt6i_metric >= IP6_RT_PRIO_ADDRCONF) rt = rt6_best_dflt(rt, fl->oif); } else { rt = rt6_device_match(rt, fl->oif, strict); BACKTRACK(); } if (ip6_rt_policy == 0) { if (!rt->rt6i_nexthop && !(rt->rt6i_flags & RTF_NONEXTHOP)) { read_unlock_bh(&rt6_lock); rt = rt6_cow(rt, fl->nl_u.ip6_u.daddr, fl->nl_u.ip6_u.saddr); if (rt->u.dst.error != -EEXIST || --attempts <= 0) goto out2; /* Race condition! In the gap, when rt6_lock was released someone could insert this route. Relookup. */ goto relookup; } dst_hold(&rt->u.dst); } else { #ifdef CONFIG_RT6_POLICY rt = rt6_flow_lookup_out(rt, sk, fl); #else /* NEVER REACHED */ #endif } out: read_unlock_bh(&rt6_lock); out2: rt->u.dst.lastuse = jiffies; rt->u.dst.__use++; return &rt->u.dst; }
static void ip6fl_seq_stop(struct seq_file *seq, void *v) { read_unlock_bh(&ip6_fl_lock); }