static int ip_proto_bind (struct socket *sock, struct sockaddr *uaddr, int addr_len) { struct sockaddr_in addr; volatile struct sock *sk, *sk2; unsigned short snum; sk = sock->data; if (sk == NULL) { printk ("Warning: sock->data = NULL: %d\n" ,__LINE__); return (0); } /* check this error. */ if (sk->state != TCP_CLOSE) return (-EIO); verify_area (uaddr, addr_len); memcpy_fromfs (&addr, uaddr, min (sizeof (addr), addr_len)); if (addr.sin_family && addr.sin_family != AF_INET) return (-EIO); /* this needs to be changed. */ snum = net16(addr.sin_port); PRINTK ("bind sk =%X to port = %d\n", sk, snum); print_sk (sk); sk = sock->data; /* we can't just leave the socket bound wherever it is, it might be bound to a priveledged port. However, since there seems to be a bug here, we will leave it if the port is not priveledged(sp?) */ if (snum == 0) { if ( sk->num > PROT_SOCK) return (0); snum = get_new_socknum (sk->prot, 0); } if (snum <= PROT_SOCK && !suser()) return (-EPERM); if (my_ip_addr(addr.sin_addr.s_addr) || addr.sin_addr.s_addr == 0) sk->saddr = addr.sin_addr.s_addr; PRINTK ("sock_array[%d] = %X:\n", snum & (SOCK_ARRAY_SIZE -1), sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]); print_sk (sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]); /* make sure we are allowed to bind here. */ for (sk2 = sk->prot->sock_array[snum & (SOCK_ARRAY_SIZE -1)]; sk2 != NULL; sk2 = sk2->next) { if (sk2->num != snum) continue; if (sk2->saddr != sk->saddr) continue; if (!sk->reuse) return (-EADDRINUSE); if (!sk2->reuse) return (-EADDRINUSE); } remove_sock (sk); put_sock(snum, sk); sk->dummy_th.source = net16(sk->num); sk->daddr = 0; sk->dummy_th.dest = 0; return (0); }
/* this will do terrible things if len + ipheader + devheader > dev->mtu */ static int packet_sendto (volatile struct sock *sk, unsigned char *from, int len, int noblock, unsigned flags, struct sockaddr_in *usin, int addr_len) { struct sk_buff *skb; struct device *dev; struct sockaddr saddr; /* check the flags. */ if (flags) return (-EINVAL); if (len < 0) return (-EINVAL); /* get and verify the address. */ if (usin) { if (addr_len < sizeof (saddr)) return (-EINVAL); verify_area (usin, sizeof (saddr)); memcpy_fromfs (&saddr, usin, sizeof(saddr)); } else return (-EINVAL); skb = sk->prot->wmalloc (sk, len+sizeof (*skb) + sk->prot->max_header, 0); /* this shouldn't happen, but it could. */ if (skb == NULL) { PRINTK ("packet_sendto: write buffer full?\n"); print_sk (sk); return (-EAGAIN); } skb->mem_addr = skb; skb->mem_len = len + sizeof (*skb) +sk->prot->max_header; skb->sk = sk; skb->free = 1; saddr.sa_data[13] = 0; dev = get_dev (saddr.sa_data); if (dev == NULL) { sk->prot->wfree (sk, skb->mem_addr, skb->mem_len); return (-ENXIO); } verify_area (from, len); memcpy_fromfs (skb+1, from, len); skb->len = len; skb->next = NULL; if (dev->up) dev->queue_xmit (skb, dev, sk->priority); else free_skb (skb, FREE_WRITE); return (len); }
static void check_result(void) { struct bpf_tcp_sock srv_tp, cli_tp; struct bpf_sock srv_sk, cli_sk; __u32 linum, idx0 = 0; int err; err = bpf_map_lookup_elem(linum_map_fd, &idx0, &linum); CHECK(err == -1, "bpf_map_lookup_elem(linum_map_fd)", "err:%d errno:%d", err, errno); err = bpf_map_lookup_elem(sk_map_fd, &srv_idx, &srv_sk); CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &srv_idx)", "err:%d errno:%d", err, errno); err = bpf_map_lookup_elem(tp_map_fd, &srv_idx, &srv_tp); CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &srv_idx)", "err:%d errno:%d", err, errno); err = bpf_map_lookup_elem(sk_map_fd, &cli_idx, &cli_sk); CHECK(err == -1, "bpf_map_lookup_elem(sk_map_fd, &cli_idx)", "err:%d errno:%d", err, errno); err = bpf_map_lookup_elem(tp_map_fd, &cli_idx, &cli_tp); CHECK(err == -1, "bpf_map_lookup_elem(tp_map_fd, &cli_idx)", "err:%d errno:%d", err, errno); printf("srv_sk: "); print_sk(&srv_sk); printf("\n"); printf("cli_sk: "); print_sk(&cli_sk); printf("\n"); printf("srv_tp: "); print_tp(&srv_tp); printf("\n"); printf("cli_tp: "); print_tp(&cli_tp); printf("\n"); CHECK(srv_sk.state == 10 || !srv_sk.state || srv_sk.family != AF_INET6 || srv_sk.protocol != IPPROTO_TCP || memcmp(srv_sk.src_ip6, &in6addr_loopback, sizeof(srv_sk.src_ip6)) || memcmp(srv_sk.dst_ip6, &in6addr_loopback, sizeof(srv_sk.dst_ip6)) || srv_sk.src_port != ntohs(srv_sa6.sin6_port) || srv_sk.dst_port != cli_sa6.sin6_port, "Unexpected srv_sk", "Check srv_sk output. linum:%u", linum); CHECK(cli_sk.state == 10 || !cli_sk.state || cli_sk.family != AF_INET6 || cli_sk.protocol != IPPROTO_TCP || memcmp(cli_sk.src_ip6, &in6addr_loopback, sizeof(cli_sk.src_ip6)) || memcmp(cli_sk.dst_ip6, &in6addr_loopback, sizeof(cli_sk.dst_ip6)) || cli_sk.src_port != ntohs(cli_sa6.sin6_port) || cli_sk.dst_port != srv_sa6.sin6_port, "Unexpected cli_sk", "Check cli_sk output. linum:%u", linum); CHECK(srv_tp.data_segs_out != 1 || srv_tp.data_segs_in || srv_tp.snd_cwnd != 10 || srv_tp.total_retrans || srv_tp.bytes_acked != DATA_LEN, "Unexpected srv_tp", "Check srv_tp output. linum:%u", linum); CHECK(cli_tp.data_segs_out || cli_tp.data_segs_in != 1 || cli_tp.snd_cwnd != 10 || cli_tp.total_retrans || cli_tp.bytes_received != DATA_LEN, "Unexpected cli_tp", "Check cli_tp output. linum:%u", linum); }
void destroy_sock(volatile struct sock *sk) { struct sk_buff *skb; PRINTK ("destroying socket %X\n",sk); /* just to be safe. */ sk->inuse = 1; remove_sock (sk); /* now we can no longer get new packets. */ delete_timer((struct timer *)&sk->time_wait); /* cleanup up the write buffer. */ for (skb = sk->wfront; skb != NULL; ) { struct sk_buff *skb2; skb2=skb->next; free_skb(skb, FREE_WRITE); skb=skb2; } sk->wfront = NULL; if (sk->rqueue != NULL) { skb = sk->rqueue; do { struct sk_buff *skb2; skb2=skb->next; /* this will take care of closing sockets that were listening and didn't accept everything. */ if (skb->sk != NULL && skb->sk != sk) { skb->sk->dead = 1; skb->sk->prot->close (skb->sk, 0); } free_skb(skb, FREE_READ); skb=skb2; } while (skb != sk->rqueue); } sk->rqueue = NULL; /* now we need to clean up the send head. */ for (skb = sk->send_head; skb != NULL; ) { struct sk_buff *skb2; /* we need to remove skb from the transmit queue. */ cli(); /* see if it's in a transmit queue. */ if (skb->next != NULL) { if (skb->next != skb) { skb->next->prev = skb->prev; skb->prev->next = skb->next; } else { int i; for (i = 0; i < DEV_NUMBUFFS; i++) { if (skb->dev && skb->dev->buffs[i] == skb) { skb->dev->buffs[i]= NULL; break; } } } } sti(); skb2=skb->link3; free_skb(skb, FREE_WRITE); skb=skb2; } sk->send_head = NULL; /* and now the backlog. */ if (sk->back_log != NULL) { /* this should never happen. */ printk ("cleaning back_log. \n"); cli(); skb = sk->back_log; do { struct sk_buff *skb2; skb2=skb->next; free_skb(skb, FREE_READ); skb=skb2; } while (skb != sk->back_log); sti(); } sk->back_log = NULL; /* now if everything is gone we can free the socket structure, otherwise we need to keep it around until everything is gone. */ if (sk->rmem_alloc == 0 && sk->wmem_alloc == 0) { free_s ((void *)sk,sizeof (*sk)); } else { /* this should never happen. */ /* actually it can if an ack has just been sent. */ PRINTK ("possible memory leak in socket = %X\n", sk); print_sk (sk); sk->destroy = 1; sk->ack_backlog = 0; sk->inuse = 0; sk->time_wait.len = SOCK_DESTROY_TIME; sk->timeout = TIME_DESTROY; reset_timer ((struct timer *)&sk->time_wait); } }