static int libcfs_sock_create (struct socket **sockp, int *fatal, __u32 local_ip, int local_port) { struct sockaddr_in locaddr; struct socket *so; struct sockopt sopt; int option; int rc; CFS_DECL_FUNNEL_DATA; *fatal = 1; CFS_NET_IN; rc = socreate(PF_INET, &so, SOCK_STREAM, 0); CFS_NET_EX; if (rc != 0) { CERROR ("Can't create socket: %d\n", rc); return (-rc); } bzero(&sopt, sizeof sopt); option = 1; sopt.sopt_level = SOL_SOCKET; sopt.sopt_name = SO_REUSEADDR; sopt.sopt_val = &option; sopt.sopt_valsize = sizeof(option); CFS_NET_IN; rc = sosetopt(so, &sopt); if (rc != 0) { CFS_NET_EX; CERROR ("Can't set sock reuse address: %d\n", rc); goto out; } /* can't specify a local port without a local IP */ LASSERT (local_ip == 0 || local_port != 0); if (local_ip != 0 || local_port != 0) { bzero (&locaddr, sizeof (locaddr)); locaddr.sin_len = sizeof(struct sockaddr_in); locaddr.sin_family = AF_INET; locaddr.sin_port = htons (local_port); locaddr.sin_addr.s_addr = (local_ip != 0) ? htonl(local_ip) : INADDR_ANY; rc = sobind(so, (struct sockaddr *)&locaddr); if (rc == EADDRINUSE) { CFS_NET_EX; CDEBUG(D_NET, "Port %d already in use\n", local_port); *fatal = 0; goto out; } if (rc != 0) { CFS_NET_EX; CERROR ("Can't bind to local IP Address %u.%u.%u.%u: %d\n", HIPQUAD(local_ip), rc); goto out; } } *sockp = so; return 0; out: CFS_NET_IN; soclose(so); CFS_NET_EX; return -rc; }
static int help(struct sk_buff **pskb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { unsigned int dataoff; struct tcphdr _tcph, *th; char *data, *data_limit, *ib_ptr; int dir = CTINFO2DIR(ctinfo); struct ip_conntrack_expect *exp; u32 seq; u_int32_t dcc_ip; u_int16_t dcc_port; int i, ret = NF_ACCEPT; char *addr_beg_p, *addr_end_p; DEBUGP("entered\n"); /* If packet is coming from IRC server */ if (dir == IP_CT_DIR_REPLY) return NF_ACCEPT; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { DEBUGP("Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } /* Not a full tcp header? */ th = skb_header_pointer(*pskb, (*pskb)->nh.iph->ihl*4, sizeof(_tcph), &_tcph); if (th == NULL) return NF_ACCEPT; /* No data? */ dataoff = (*pskb)->nh.iph->ihl*4 + th->doff*4; if (dataoff >= (*pskb)->len) return NF_ACCEPT; spin_lock_bh(&irc_buffer_lock); ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, irc_buffer); BUG_ON(ib_ptr == NULL); data = ib_ptr; data_limit = ib_ptr + (*pskb)->len - dataoff; /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ while (data < (data_limit - (19 + MINMATCHLEN))) { if (memcmp(data, "\1DCC ", 5)) { data++; continue; } data += 5; /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n", NIPQUAD(iph->saddr), ntohs(th->source), NIPQUAD(iph->daddr), ntohs(th->dest)); for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { /* no match */ continue; } DEBUGP("DCC %s detected\n", dccprotos[i]); data += strlen(dccprotos[i]); /* we have at least * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid * data left (== 14/13 bytes) */ if (parse_dcc((char *)data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) { /* unable to parse */ DEBUGP("unable to parse dcc command\n"); continue; } DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n", HIPQUAD(dcc_ip), dcc_port); /* dcc_ip can be the internal OR external (NAT'ed) IP * Tiago Sousa <*****@*****.**> */ if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip) && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != htonl(dcc_ip)) { if (net_ratelimit()) printk(KERN_WARNING "Forged DCC command from " "%u.%u.%u.%u: %u.%u.%u.%u:%u\n", NIPQUAD(ct->tuplehash[dir].tuple.src.ip), HIPQUAD(dcc_ip), dcc_port); continue; } exp = ip_conntrack_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; } /* save position of address in dcc string, * necessary for NAT */ DEBUGP("tcph->seq = %u\n", th->seq); seq = ntohl(th->seq) + (addr_beg_p - ib_ptr); /* We refer to the reverse direction ("!dir") * tuples here, because we're expecting * something in the other * direction. * Doesn't matter unless NAT is happening. */ exp->tuple = ((struct ip_conntrack_tuple) { { 0, { 0 } }, { ct->tuplehash[!dir].tuple.dst.ip, { .tcp = { htons(dcc_port) } }, IPPROTO_TCP }});
/* * XXX Liang: timeout for write is not supported yet. */ int libcfs_sock_write (struct socket *sock, void *buffer, int nob, int timeout) { int rc; CFS_DECL_NET_DATA; while (nob > 0) { struct iovec iov = { .iov_base = buffer, .iov_len = nob }; struct uio suio = { .uio_iov = &iov, .uio_iovcnt = 1, .uio_offset = 0, .uio_resid = nob, .uio_segflg = UIO_SYSSPACE, .uio_rw = UIO_WRITE, .uio_procp = NULL }; CFS_NET_IN; rc = sosend(sock, NULL, &suio, (struct mbuf *)0, (struct mbuf *)0, 0); CFS_NET_EX; if (rc != 0) { if ( suio.uio_resid != nob && ( rc == ERESTART || rc == EINTR ||\ rc == EWOULDBLOCK)) rc = 0; if ( rc != 0 ) return -rc; rc = nob - suio.uio_resid; buffer = ((char *)buffer) + rc; nob = suio.uio_resid; continue; } break; } return (0); } /* * XXX Liang: timeout for read is not supported yet. */ int libcfs_sock_read (struct socket *sock, void *buffer, int nob, int timeout) { int rc; CFS_DECL_NET_DATA; while (nob > 0) { struct iovec iov = { .iov_base = buffer, .iov_len = nob }; struct uio ruio = { .uio_iov = &iov, .uio_iovcnt = 1, .uio_offset = 0, .uio_resid = nob, .uio_segflg = UIO_SYSSPACE, .uio_rw = UIO_READ, .uio_procp = NULL }; CFS_NET_IN; rc = soreceive(sock, (struct sockaddr **)0, &ruio, (struct mbuf **)0, (struct mbuf **)0, (int *)0); CFS_NET_EX; if (rc != 0) { if ( ruio.uio_resid != nob && ( rc == ERESTART || rc == EINTR ||\ rc == EWOULDBLOCK)) rc = 0; if (rc != 0) return -rc; rc = nob - ruio.uio_resid; buffer = ((char *)buffer) + rc; nob = ruio.uio_resid; continue; } break; } return (0); } int libcfs_sock_setbuf (struct socket *sock, int txbufsize, int rxbufsize) { struct sockopt sopt; int rc = 0; int option; CFS_DECL_NET_DATA; bzero(&sopt, sizeof sopt); sopt.sopt_dir = SOPT_SET; sopt.sopt_level = SOL_SOCKET; sopt.sopt_val = &option; sopt.sopt_valsize = sizeof(option); if (txbufsize != 0) { option = txbufsize; if (option > KSOCK_MAX_BUF) option = KSOCK_MAX_BUF; sopt.sopt_name = SO_SNDBUF; CFS_NET_IN; rc = sosetopt(sock, &sopt); CFS_NET_EX; if (rc != 0) { CERROR ("Can't set send buffer %d: %d\n", option, rc); return -rc; } } if (rxbufsize != 0) { option = rxbufsize; sopt.sopt_name = SO_RCVBUF; CFS_NET_IN; rc = sosetopt(sock, &sopt); CFS_NET_EX; if (rc != 0) { CERROR ("Can't set receive buffer %d: %d\n", option, rc); return -rc; } } return 0; } int libcfs_sock_getaddr (struct socket *sock, int remote, __u32 *ip, int *port) { struct sockaddr_in *sin; struct sockaddr *sa = NULL; int rc; CFS_DECL_NET_DATA; if (remote != 0) { CFS_NET_IN; rc = sock->so_proto->pr_usrreqs->pru_peeraddr(sock, &sa); CFS_NET_EX; if (rc != 0) { if (sa) FREE(sa, M_SONAME); CERROR ("Error %d getting sock peer IP\n", rc); return -rc; } } else { CFS_NET_IN; rc = sock->so_proto->pr_usrreqs->pru_sockaddr(sock, &sa); CFS_NET_EX; if (rc != 0) { if (sa) FREE(sa, M_SONAME); CERROR ("Error %d getting sock local IP\n", rc); return -rc; } } if (sa != NULL) { sin = (struct sockaddr_in *)sa; if (ip != NULL) *ip = ntohl (sin->sin_addr.s_addr); if (port != NULL) *port = ntohs (sin->sin_port); if (sa) FREE(sa, M_SONAME); } return 0; } int libcfs_sock_getbuf (struct socket *sock, int *txbufsize, int *rxbufsize) { struct sockopt sopt; int rc; CFS_DECL_NET_DATA; bzero(&sopt, sizeof sopt); sopt.sopt_dir = SOPT_GET; sopt.sopt_level = SOL_SOCKET; if (txbufsize != NULL) { sopt.sopt_val = txbufsize; sopt.sopt_valsize = sizeof(*txbufsize); sopt.sopt_name = SO_SNDBUF; CFS_NET_IN; rc = sogetopt(sock, &sopt); CFS_NET_EX; if (rc != 0) { CERROR ("Can't get send buffer size: %d\n", rc); return -rc; } } if (rxbufsize != NULL) { sopt.sopt_val = rxbufsize; sopt.sopt_valsize = sizeof(*rxbufsize); sopt.sopt_name = SO_RCVBUF; CFS_NET_IN; rc = sogetopt(sock, &sopt); CFS_NET_EX; if (rc != 0) { CERROR ("Can't get receive buffer size: %d\n", rc); return -rc; } } return 0; } int libcfs_sock_connect (struct socket **sockp, int *fatal, __u32 local_ip, int local_port, __u32 peer_ip, int peer_port) { struct sockaddr_in srvaddr; struct socket *so; int s; int rc; CFS_DECL_FUNNEL_DATA; rc = libcfs_sock_create(sockp, fatal, local_ip, local_port); if (rc != 0) return rc; so = *sockp; bzero(&srvaddr, sizeof(srvaddr)); srvaddr.sin_len = sizeof(struct sockaddr_in); srvaddr.sin_family = AF_INET; srvaddr.sin_port = htons (peer_port); srvaddr.sin_addr.s_addr = htonl (peer_ip); CFS_NET_IN; rc = soconnect(so, (struct sockaddr *)&srvaddr); if (rc != 0) { CFS_NET_EX; if (rc != EADDRNOTAVAIL && rc != EADDRINUSE) CDEBUG(D_NETERROR, "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc, HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port); goto out; } s = splnet(); while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) { CDEBUG(D_NET, "ksocknal sleep for waiting auto_connect.\n"); (void) tsleep((caddr_t)&so->so_timeo, PSOCK, "ksocknal_conn", hz); } if ((rc = so->so_error) != 0) { so->so_error = 0; splx(s); CFS_NET_EX; CDEBUG(D_NETERROR, "Error %d connecting %u.%u.%u.%u/%d -> %u.%u.%u.%u/%d\n", rc, HIPQUAD(local_ip), local_port, HIPQUAD(peer_ip), peer_port); goto out; } LASSERT(so->so_state & SS_ISCONNECTED); splx(s); CFS_NET_EX; if (sockp) *sockp = so; return (0); out: CFS_NET_IN; soshutdown(so, 2); soclose(so); CFS_NET_EX; return (-rc); } void libcfs_sock_release (struct socket *sock) { CFS_DECL_FUNNEL_DATA; CFS_NET_IN; soshutdown(sock, 0); CFS_NET_EX; }
int lnet_acceptor(void *arg) { char name[16]; cfs_socket_t *newsock; int rc; __u32 magic; __u32 peer_ip; int peer_port; int secure = (int)((long_ptr_t)arg); LASSERT (lnet_acceptor_state.pta_sock == NULL); snprintf(name, sizeof(name), "acceptor_%03d", accept_port); cfs_daemonize(name); cfs_block_allsigs(); rc = libcfs_sock_listen(&lnet_acceptor_state.pta_sock, 0, accept_port, accept_backlog); if (rc != 0) { if (rc == -EADDRINUSE) LCONSOLE_ERROR_MSG(0x122, "Can't start acceptor on port" " %d: port already in use\n", accept_port); else LCONSOLE_ERROR_MSG(0x123, "Can't start acceptor on port " "%d: unexpected error %d\n", accept_port, rc); lnet_acceptor_state.pta_sock = NULL; } else { LCONSOLE(0, "Accept %s, port %d\n", accept_type, accept_port); } /* set init status and unblock parent */ lnet_acceptor_state.pta_shutdown = rc; cfs_mt_complete(&lnet_acceptor_state.pta_signal); if (rc != 0) return rc; while (!lnet_acceptor_state.pta_shutdown) { rc = libcfs_sock_accept(&newsock, lnet_acceptor_state.pta_sock); if (rc != 0) { if (rc != -EAGAIN) { CWARN("Accept error %d: pausing...\n", rc); cfs_pause(cfs_time_seconds(1)); } continue; } /* maybe we're waken up with libcfs_sock_abort_accept() */ if (lnet_acceptor_state.pta_shutdown) { libcfs_sock_release(newsock); break; } rc = libcfs_sock_getaddr(newsock, 1, &peer_ip, &peer_port); if (rc != 0) { CERROR("Can't determine new connection's address\n"); goto failed; } if (secure && peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) { CERROR("Refusing connection from %u.%u.%u.%u: " "insecure port %d\n", HIPQUAD(peer_ip), peer_port); goto failed; } rc = libcfs_sock_read(newsock, &magic, sizeof(magic), accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from " "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip)); goto failed; } rc = lnet_accept(newsock, magic); if (rc != 0) goto failed; continue; failed: libcfs_sock_release(newsock); } libcfs_sock_release(lnet_acceptor_state.pta_sock); lnet_acceptor_state.pta_sock = NULL; LCONSOLE(0, "Acceptor stopping\n"); /* unblock lnet_acceptor_stop() */ cfs_mt_complete(&lnet_acceptor_state.pta_signal); return 0; }
/* FIXME: This should be in userspace. Later. */ static int help(const struct iphdr *iph, size_t len, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { /* tcplen not negative guarenteed by ip_conntrack_tcp.c */ struct tcphdr *tcph = (void *) iph + iph->ihl * 4; const char *data = (const char *) tcph + tcph->doff * 4; const char *_data = data; char *data_limit; u_int32_t tcplen = len - iph->ihl * 4; u_int32_t datalen = tcplen - tcph->doff * 4; int dir = CTINFO2DIR(ctinfo); struct ip_conntrack_expect expect, *exp = &expect; struct ip_ct_irc_expect *exp_irc_info = &exp->help.exp_irc_info; u_int32_t dcc_ip; u_int16_t dcc_port; int i; char *addr_beg_p, *addr_end_p; DEBUGP("entered\n"); /* If packet is coming from IRC server */ if (dir == IP_CT_DIR_REPLY) return NF_ACCEPT; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { DEBUGP("Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } /* Not whole TCP header? */ if (tcplen < sizeof(struct tcphdr) || tcplen < tcph->doff * 4) { DEBUGP("tcplen = %u\n", (unsigned) tcplen); return NF_ACCEPT; } /* Checksum invalid? Ignore. */ /* FIXME: Source route IP option packets --RR */ if (tcp_v4_check(tcph, tcplen, iph->saddr, iph->daddr, csum_partial((char *) tcph, tcplen, 0))) { DEBUGP("bad csum: %p %u %u.%u.%u.%u %u.%u.%u.%u\n", tcph, tcplen, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr)); return NF_ACCEPT; } data_limit = (char *) data + datalen; /* strlen("\1DCC SEND t AAAAAAAA P\1\n")=24 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ while (data < (data_limit - (19 + MINMATCHLEN))) { if (memcmp(data, "\1DCC ", 5)) { data++; continue; } data += 5; /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n", NIPQUAD(iph->saddr), ntohs(tcph->source), NIPQUAD(iph->daddr), ntohs(tcph->dest)); for (i = 0; i < NUM_DCCPROTO; i++) { if (memcmp(data, dccprotos[i].match, dccprotos[i].matchlen)) { /* no match */ continue; } DEBUGP("DCC %s detected\n", dccprotos[i].match); data += dccprotos[i].matchlen; /* we have at least * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid * data left (== 14/13 bytes) */ if (parse_dcc((char *) data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) { /* unable to parse */ DEBUGP("unable to parse dcc command\n"); continue; } DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n", HIPQUAD(dcc_ip), dcc_port); if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip)) { if (net_ratelimit()) printk(KERN_WARNING "Forged DCC command from " "%u.%u.%u.%u: %u.%u.%u.%u:%u\n", NIPQUAD(ct->tuplehash[dir].tuple.src.ip), HIPQUAD(dcc_ip), dcc_port); continue; } memset(&expect, 0, sizeof(expect)); LOCK_BH(&ip_irc_lock); /* save position of address in dcc string, * neccessary for NAT */ DEBUGP("tcph->seq = %u\n", tcph->seq); exp->seq = ntohl(tcph->seq) + (addr_beg_p - _data); exp_irc_info->len = (addr_end_p - addr_beg_p); exp_irc_info->port = dcc_port; DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n", exp->seq, (addr_end_p - _data), exp_irc_info->len); exp->tuple = ((struct ip_conntrack_tuple) { { 0, { 0 } }, { htonl(dcc_ip), { .tcp = { htons(dcc_port) } }, IPPROTO_TCP }});
int netpoll_setup(struct netpoll *np) { struct net_device *ndev = NULL; struct in_device *in_dev; struct netpoll_info *npinfo; unsigned long flags; int err; if (np->dev_name) ndev = dev_get_by_name(np->dev_name); if (!ndev) { printk(KERN_ERR "%s: %s doesn't exist, aborting.\n", np->name, np->dev_name); return -ENODEV; } np->dev = ndev; if (!ndev->npinfo) { npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); if (!npinfo) { err = -ENOMEM; goto release; } npinfo->rx_flags = 0; npinfo->rx_np = NULL; spin_lock_init(&npinfo->poll_lock); npinfo->poll_owner = -1; spin_lock_init(&npinfo->rx_lock); skb_queue_head_init(&npinfo->arp_tx); skb_queue_head_init(&npinfo->txq); INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); atomic_set(&npinfo->refcnt, 1); } else { npinfo = ndev->npinfo; atomic_inc(&npinfo->refcnt); } if (!ndev->poll_controller) { printk(KERN_ERR "%s: %s doesn't support polling, aborting.\n", np->name, np->dev_name); err = -ENOTSUPP; goto release; } if (!netif_running(ndev)) { unsigned long atmost, atleast; printk(KERN_INFO "%s: device %s not up yet, forcing it\n", np->name, np->dev_name); rtnl_lock(); err = dev_open(ndev); rtnl_unlock(); if (err) { printk(KERN_ERR "%s: failed to open %s\n", np->name, ndev->name); goto release; } atleast = jiffies + HZ/10; atmost = jiffies + 4*HZ; while (!netif_carrier_ok(ndev)) { if (time_after(jiffies, atmost)) { printk(KERN_NOTICE "%s: timeout waiting for carrier\n", np->name); break; } cond_resched(); } /* If carrier appears to come up instantly, we don't * trust it and pause so that we don't pump all our * queued console messages into the bitbucket. */ if (time_before(jiffies, atleast)) { printk(KERN_NOTICE "%s: carrier detect appears" " untrustworthy, waiting 4 seconds\n", np->name); msleep(4000); } } if (is_zero_ether_addr(np->local_mac) && ndev->dev_addr) memcpy(np->local_mac, ndev->dev_addr, 6); if (!np->local_ip) { rcu_read_lock(); in_dev = __in_dev_get_rcu(ndev); if (!in_dev || !in_dev->ifa_list) { rcu_read_unlock(); printk(KERN_ERR "%s: no IP address for %s, aborting\n", np->name, np->dev_name); err = -EDESTADDRREQ; goto release; } np->local_ip = ntohl(in_dev->ifa_list->ifa_local); rcu_read_unlock(); printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n", np->name, HIPQUAD(np->local_ip)); } if (np->rx_hook) { spin_lock_irqsave(&npinfo->rx_lock, flags); npinfo->rx_flags |= NETPOLL_RX_ENABLED; npinfo->rx_np = np; spin_unlock_irqrestore(&npinfo->rx_lock, flags); } /* fill up the skb queue */ refill_skbs(); /* last thing to do is link it to the net device structure */ ndev->npinfo = npinfo; /* avoid racing with NAPI reading npinfo */ synchronize_rcu(); return 0; release: if (!ndev->npinfo) kfree(npinfo); np->dev = NULL; dev_put(ndev); return err; }
int lnet_accept(cfs_socket_t *sock, __u32 magic) { lnet_acceptor_connreq_t cr; __u32 peer_ip; int peer_port; int rc; int flip; lnet_ni_t *ni; char *str; LASSERT (sizeof(cr) <= 16); /* not too big for the stack */ rc = libcfs_sock_getaddr(sock, 1, &peer_ip, &peer_port); LASSERT (rc == 0); /* we succeeded before */ if (!lnet_accept_magic(magic, LNET_PROTO_ACCEPTOR_MAGIC)) { if (lnet_accept_magic(magic, LNET_PROTO_MAGIC)) { /* future version compatibility! * When LNET unifies protocols over all LNDs, the first * thing sent will be a version query. I send back * LNET_PROTO_ACCEPTOR_MAGIC to tell her I'm "old" */ memset (&cr, 0, sizeof(cr)); cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC; cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; rc = libcfs_sock_write(sock, &cr, sizeof(cr), accept_timeout); if (rc != 0) CERROR("Error sending magic+version in response" "to LNET magic from %u.%u.%u.%u: %d\n", HIPQUAD(peer_ip), rc); return -EPROTO; } if (magic == le32_to_cpu(LNET_PROTO_TCP_MAGIC)) str = "'old' socknal/tcpnal"; else if (lnet_accept_magic(magic, LNET_PROTO_RA_MAGIC)) str = "'old' ranal"; else str = "unrecognised"; LCONSOLE_ERROR_MSG(0x11f, "Refusing connection from %u.%u.%u.%u" " magic %08x: %s acceptor protocol\n", HIPQUAD(peer_ip), magic, str); return -EPROTO; } flip = (magic != LNET_PROTO_ACCEPTOR_MAGIC); rc = libcfs_sock_read(sock, &cr.acr_version, sizeof(cr.acr_version), accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request version from " "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip)); return -EIO; } if (flip) __swab32s(&cr.acr_version); if (cr.acr_version != LNET_PROTO_ACCEPTOR_VERSION) { /* future version compatibility! * An acceptor-specific protocol rev will first send a version * query. I send back my current version to tell her I'm * "old". */ int peer_version = cr.acr_version; memset (&cr, 0, sizeof(cr)); cr.acr_magic = LNET_PROTO_ACCEPTOR_MAGIC; cr.acr_version = LNET_PROTO_ACCEPTOR_VERSION; rc = libcfs_sock_write(sock, &cr, sizeof(cr), accept_timeout); if (rc != 0) CERROR("Error sending magic+version in response" "to version %d from %u.%u.%u.%u: %d\n", peer_version, HIPQUAD(peer_ip), rc); return -EPROTO; } rc = libcfs_sock_read(sock, &cr.acr_nid, sizeof(cr) - offsetof(lnet_acceptor_connreq_t, acr_nid), accept_timeout); if (rc != 0) { CERROR("Error %d reading connection request from " "%u.%u.%u.%u\n", rc, HIPQUAD(peer_ip)); return -EIO; } if (flip) __swab64s(&cr.acr_nid); ni = lnet_net2ni(LNET_NIDNET(cr.acr_nid)); if (ni == NULL || /* no matching net */ ni->ni_nid != cr.acr_nid) { /* right NET, wrong NID! */ if (ni != NULL) lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x120, "Refusing connection from %u.%u.%u.%u" " for %s: No matching NI\n", HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid)); return -EPERM; } if (ni->ni_lnd->lnd_accept == NULL) { /* This catches a request for the loopback LND */ lnet_ni_decref(ni); LCONSOLE_ERROR_MSG(0x121, "Refusing connection from %u.%u.%u.%u" " for %s: NI doesn not accept IP connections\n", HIPQUAD(peer_ip), libcfs_nid2str(cr.acr_nid)); return -EPERM; } CDEBUG(D_NET, "Accept %s from %u.%u.%u.%u\n", libcfs_nid2str(cr.acr_nid), HIPQUAD(peer_ip)); rc = ni->ni_lnd->lnd_accept(ni, sock); lnet_ni_decref(ni); return rc; }
/* All actions that we need after receiving hello on passive conn: * 1) Stash peer's nid, pid, incarnation and conn type * 2) Cope with easy case: conn[idx] is empty - just save conn there * 3) Resolve race: * a) if our nid is higher - reply with CONN_NONE and make us zombie * b) if peer's nid is higher - postpone race resolution till * READY state * 4) Anyhow, send reply hello */ int usocklnd_passiveconn_hellorecv(usock_conn_t *conn) { ksock_hello_msg_t *hello = conn->uc_rx_hello; int type; int idx; int rc; usock_peer_t *peer; lnet_ni_t *ni = conn->uc_ni; __u32 peer_ip = conn->uc_peer_ip; __u16 peer_port = conn->uc_peer_port; /* don't know parent peer yet and not zombie */ LASSERT (conn->uc_peer == NULL && ni != NULL); /* don't know peer's nid and incarnation yet */ if (peer_port > LNET_ACCEPTOR_MAX_RESERVED_PORT) { /* do not trust liblustre clients */ conn->uc_peerid.pid = peer_port | LNET_PID_USERFLAG; conn->uc_peerid.nid = LNET_MKNID(LNET_NIDNET(ni->ni_nid), peer_ip); if (hello->kshm_ctype != SOCKLND_CONN_ANY) { lnet_ni_decref(ni); conn->uc_ni = NULL; CERROR("Refusing to accept connection of type=%d from " "userspace process %u.%u.%u.%u:%d\n", hello->kshm_ctype, HIPQUAD(peer_ip), peer_port); return -EINVAL; } } else { conn->uc_peerid.pid = hello->kshm_src_pid; conn->uc_peerid.nid = hello->kshm_src_nid; } conn->uc_type = type = usocklnd_invert_type(hello->kshm_ctype); rc = usocklnd_find_or_create_peer(ni, conn->uc_peerid, &peer); if (rc) { lnet_ni_decref(ni); conn->uc_ni = NULL; return rc; } peer->up_last_alive = cfs_time_current(); idx = usocklnd_type2idx(conn->uc_type); /* safely check whether we're first */ pthread_mutex_lock(&peer->up_lock); usocklnd_cleanup_stale_conns(peer, hello->kshm_src_incarnation, NULL); if (peer->up_conns[idx] == NULL) { peer->up_last_alive = cfs_time_current(); conn->uc_peer = peer; conn->uc_ni = NULL; usocklnd_link_conn_to_peer(conn, peer, idx); usocklnd_conn_addref(conn); } else { usocklnd_peer_decref(peer); /* Resolve race in favour of higher NID */ if (conn->uc_peerid.nid < conn->uc_ni->ni_nid) { /* make us zombie */ conn->uc_ni = NULL; type = SOCKLND_CONN_NONE; } /* if conn->uc_peerid.nid > conn->uc_ni->ni_nid, * postpone race resolution till READY state * (hopefully that conn[idx] will die because of * incoming hello of CONN_NONE type) */ } pthread_mutex_unlock(&peer->up_lock); /* allocate and initialize fake tx with hello */ conn->uc_tx_hello = usocklnd_create_hello_tx(ni, type, conn->uc_peerid.nid); if (conn->uc_ni == NULL) lnet_ni_decref(ni); if (conn->uc_tx_hello == NULL) return -ENOMEM; /* rc == 0 */ pthread_mutex_lock(&conn->uc_lock); if (conn->uc_state == UC_DEAD) goto passive_hellorecv_done; conn->uc_state = UC_SENDING_HELLO; conn->uc_tx_deadline = cfs_time_shift(usock_tuns.ut_timeout); conn->uc_tx_flag = 1; rc = usocklnd_add_pollrequest(conn, POLL_SET_REQUEST, POLLOUT); passive_hellorecv_done: pthread_mutex_unlock(&conn->uc_lock); return rc; }
int netpoll_parse_options(struct netpoll *np, char *opt) { char *cur=opt, *delim; if (*cur != '@') { if ((delim = strchr(cur, '@')) == NULL) goto parse_failed; *delim = 0; np->local_port = simple_strtol(cur, NULL, 10); cur = delim; } cur++; printk(KERN_INFO "%s: local port %d\n", np->name, np->local_port); if (*cur != '/') { if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; *delim = 0; np->local_ip = ntohl(in_aton(cur)); cur = delim; printk(KERN_INFO "%s: local IP %d.%d.%d.%d\n", np->name, HIPQUAD(np->local_ip)); } cur++; if (*cur != ',') { /* parse out dev name */ if ((delim = strchr(cur, ',')) == NULL) goto parse_failed; *delim = 0; strlcpy(np->dev_name, cur, sizeof(np->dev_name)); cur = delim; } cur++; printk(KERN_INFO "%s: interface %s\n", np->name, np->dev_name); if (*cur != '@') { /* dst port */ if ((delim = strchr(cur, '@')) == NULL) goto parse_failed; *delim = 0; np->remote_port = simple_strtol(cur, NULL, 10); cur = delim; } cur++; printk(KERN_INFO "%s: remote port %d\n", np->name, np->remote_port); /* dst ip */ if ((delim = strchr(cur, '/')) == NULL) goto parse_failed; *delim = 0; np->remote_ip = ntohl(in_aton(cur)); cur = delim + 1; printk(KERN_INFO "%s: remote IP %d.%d.%d.%d\n", np->name, HIPQUAD(np->remote_ip)); if (*cur != 0) { /* MAC address */ if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; *delim = 0; np->remote_mac[0] = simple_strtol(cur, NULL, 16); cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; *delim = 0; np->remote_mac[1] = simple_strtol(cur, NULL, 16); cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; *delim = 0; np->remote_mac[2] = simple_strtol(cur, NULL, 16); cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; *delim = 0; np->remote_mac[3] = simple_strtol(cur, NULL, 16); cur = delim + 1; if ((delim = strchr(cur, ':')) == NULL) goto parse_failed; *delim = 0; np->remote_mac[4] = simple_strtol(cur, NULL, 16); cur = delim + 1; np->remote_mac[5] = simple_strtol(cur, NULL, 16); } printk(KERN_INFO "%s: remote ethernet address " "%02x:%02x:%02x:%02x:%02x:%02x\n", np->name, np->remote_mac[0], np->remote_mac[1], np->remote_mac[2], np->remote_mac[3], np->remote_mac[4], np->remote_mac[5]); return 0; parse_failed: printk(KERN_INFO "%s: couldn't parse config at %s!\n", np->name, cur); return -1; }
static int help(struct sk_buff **pskb, unsigned int protoff, struct nf_conn *ct, enum ip_conntrack_info ctinfo) { unsigned int dataoff; struct iphdr *iph; struct tcphdr _tcph, *th; char *data, *data_limit, *ib_ptr; int dir = CTINFO2DIR(ctinfo); struct nf_conntrack_expect *exp; struct nf_conntrack_tuple *tuple; u_int32_t dcc_ip; u_int16_t dcc_port; __be16 port; int i, ret = NF_ACCEPT; char *addr_beg_p, *addr_end_p; typeof(nf_nat_irc_hook) nf_nat_irc; /* If packet is coming from IRC server */ if (dir == IP_CT_DIR_REPLY) return NF_ACCEPT; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) return NF_ACCEPT; /* Not a full tcp header? */ th = skb_header_pointer(*pskb, protoff, sizeof(_tcph), &_tcph); if (th == NULL) return NF_ACCEPT; /* No data? */ dataoff = protoff + th->doff*4; if (dataoff >= (*pskb)->len) return NF_ACCEPT; spin_lock_bh(&irc_buffer_lock); ib_ptr = skb_header_pointer(*pskb, dataoff, (*pskb)->len - dataoff, irc_buffer); BUG_ON(ib_ptr == NULL); data = ib_ptr; data_limit = ib_ptr + (*pskb)->len - dataoff; /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ while (data < data_limit - (19 + MINMATCHLEN)) { if (memcmp(data, "\1DCC ", 5)) { data++; continue; } data += 5; /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ iph = ip_hdr(*pskb); pr_debug("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u\n", NIPQUAD(iph->saddr), ntohs(th->source), NIPQUAD(iph->daddr), ntohs(th->dest)); for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { /* no match */ continue; } data += strlen(dccprotos[i]); pr_debug("DCC %s detected\n", dccprotos[i]); /* we have at least * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid * data left (== 14/13 bytes) */ if (parse_dcc((char *)data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) { pr_debug("unable to parse dcc command\n"); continue; } pr_debug("DCC bound ip/port: %u.%u.%u.%u:%u\n", HIPQUAD(dcc_ip), dcc_port); /* dcc_ip can be the internal OR external (NAT'ed) IP */ tuple = &ct->tuplehash[dir].tuple; if (tuple->src.u3.ip != htonl(dcc_ip) && tuple->dst.u3.ip != htonl(dcc_ip)) { if (net_ratelimit()) printk(KERN_WARNING "Forged DCC command from " "%u.%u.%u.%u: %u.%u.%u.%u:%u\n", NIPQUAD(tuple->src.u3.ip), HIPQUAD(dcc_ip), dcc_port); continue; } exp = nf_ct_expect_alloc(ct); if (exp == NULL) { ret = NF_DROP; goto out; } tuple = &ct->tuplehash[!dir].tuple; port = htons(dcc_port); nf_ct_expect_init(exp, tuple->src.l3num, NULL, &tuple->dst.u3, IPPROTO_TCP, NULL, &port); nf_nat_irc = rcu_dereference(nf_nat_irc_hook); if (nf_nat_irc && ct->status & IPS_NAT_MASK) ret = nf_nat_irc(pskb, ctinfo, addr_beg_p - ib_ptr, addr_end_p - addr_beg_p, exp); else if (nf_ct_expect_related(exp) != 0) ret = NF_DROP; nf_ct_expect_put(exp); goto out; } } out: spin_unlock_bh(&irc_buffer_lock); return ret; }
/* Switch on rx_state. * Return 0 on success, else return <0 * Always set cont_flag: 1 if we're ready to continue reading, else 0 */ int usocklnd_read_hello(usock_conn_t *conn, int *cont_flag) { int rc = 0; ksock_hello_msg_t *hello = conn->uc_rx_hello; *cont_flag = 0; /* smth. new emerged in hello - let's process it */ switch (conn->uc_rx_state) { case UC_RX_HELLO_MAGIC: if (hello->kshm_magic == LNET_PROTO_MAGIC) conn->uc_flip = 0; else if (hello->kshm_magic == __swab32(LNET_PROTO_MAGIC)) conn->uc_flip = 1; else return -EPROTO; usocklnd_rx_helloversion_state_transition(conn); *cont_flag = 1; break; case UC_RX_HELLO_VERSION: if ((!conn->uc_flip && (hello->kshm_version != KSOCK_PROTO_V2)) || (conn->uc_flip && (hello->kshm_version != __swab32(KSOCK_PROTO_V2)))) return -EPROTO; usocklnd_rx_hellobody_state_transition(conn); *cont_flag = 1; break; case UC_RX_HELLO_BODY: if (conn->uc_flip) { ksock_hello_msg_t *hello = conn->uc_rx_hello; __swab32s(&hello->kshm_src_pid); __swab64s(&hello->kshm_src_nid); __swab32s(&hello->kshm_dst_pid); __swab64s(&hello->kshm_dst_nid); __swab64s(&hello->kshm_src_incarnation); __swab64s(&hello->kshm_dst_incarnation); __swab32s(&hello->kshm_ctype); __swab32s(&hello->kshm_nips); } if (conn->uc_rx_hello->kshm_nips > LNET_MAX_INTERFACES) { CERROR("Bad nips %d from ip %u.%u.%u.%u port %d\n", conn->uc_rx_hello->kshm_nips, HIPQUAD(conn->uc_peer_ip), conn->uc_peer_port); return -EPROTO; } if (conn->uc_rx_hello->kshm_nips) { usocklnd_rx_helloIPs_state_transition(conn); *cont_flag = 1; break; } /* fall through */ case UC_RX_HELLO_IPS: if (conn->uc_activeflag == 1) /* active conn */ rc = usocklnd_activeconn_hellorecv(conn); else /* passive conn */ rc = usocklnd_passiveconn_hellorecv(conn); break; default: LBUG(); /* unknown state */ } return rc; }
static int help(struct sk_buff *skb, struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) { unsigned int dataoff; struct tcphdr tcph; char *data, *data_limit; int dir = CTINFO2DIR(ctinfo); struct ip_conntrack_expect *exp; struct ip_ct_irc_expect *exp_irc_info = NULL; u_int32_t dcc_ip; u_int16_t dcc_port; int i; char *addr_beg_p, *addr_end_p; DEBUGP("entered\n"); /* If packet is coming from IRC server */ if (dir == IP_CT_DIR_REPLY) return NF_ACCEPT; /* Until there's been traffic both ways, don't look in packets. */ if (ctinfo != IP_CT_ESTABLISHED && ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY) { DEBUGP("Conntrackinfo = %u\n", ctinfo); return NF_ACCEPT; } /* Not a full tcp header? */ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &tcph, sizeof(tcph)) != 0) return NF_ACCEPT; /* No data? */ dataoff = skb->nh.iph->ihl*4 + tcph.doff*4; if (dataoff >= skb->len) return NF_ACCEPT; LOCK_BH(&ip_irc_lock); skb_copy_bits(skb, dataoff, irc_buffer, skb->len - dataoff); data = irc_buffer; data_limit = irc_buffer + skb->len - dataoff; /* strlen("\1DCC SENT t AAAAAAAA P\1\n")=24 * 5+MINMATCHLEN+strlen("t AAAAAAAA P\1\n")=14 */ while (data < (data_limit - (19 + MINMATCHLEN))) { if (memcmp(data, "\1DCC ", 5)) { data++; continue; } data += 5; /* we have at least (19+MINMATCHLEN)-5 bytes valid data left */ DEBUGP("DCC found in master %u.%u.%u.%u:%u %u.%u.%u.%u:%u...\n", NIPQUAD(iph->saddr), ntohs(tcph.source), NIPQUAD(iph->daddr), ntohs(tcph.dest)); for (i = 0; i < ARRAY_SIZE(dccprotos); i++) { if (memcmp(data, dccprotos[i], strlen(dccprotos[i]))) { /* no match */ continue; } DEBUGP("DCC %s detected\n", dccprotos[i]); data += strlen(dccprotos[i]); /* we have at least * (19+MINMATCHLEN)-5-dccprotos[i].matchlen bytes valid * data left (== 14/13 bytes) */ if (parse_dcc((char *)data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) { /* unable to parse */ DEBUGP("unable to parse dcc command\n"); continue; } DEBUGP("DCC bound ip/port: %u.%u.%u.%u:%u\n", HIPQUAD(dcc_ip), dcc_port); /* dcc_ip can be the internal OR external (NAT'ed) IP * Tiago Sousa <*****@*****.**> */ if (ct->tuplehash[dir].tuple.src.ip != htonl(dcc_ip) && ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.ip != htonl(dcc_ip)) { if (net_ratelimit()) printk(KERN_WARNING "Forged DCC command from " "%u.%u.%u.%u: %u.%u.%u.%u:%u\n", NIPQUAD(ct->tuplehash[dir].tuple.src.ip), HIPQUAD(dcc_ip), dcc_port); continue; } exp = ip_conntrack_expect_alloc(); if (exp == NULL) goto out; exp_irc_info = &exp->help.exp_irc_info; /* save position of address in dcc string, * necessary for NAT */ DEBUGP("tcph->seq = %u\n", tcph.seq); exp->seq = ntohl(tcph.seq) + (addr_beg_p - irc_buffer); exp_irc_info->len = (addr_end_p - addr_beg_p); exp_irc_info->port = dcc_port; DEBUGP("wrote info seq=%u (ofs=%u), len=%d\n", exp->seq, (addr_end_p - _data), exp_irc_info->len); exp->tuple = ((struct ip_conntrack_tuple) { { 0, { 0 } }, { ct->tuplehash[dir].tuple.src.ip, { .tcp = { htons(dcc_port) } }, IPPROTO_TCP }});
static int create(struct ip_set *set, const void *data, size_t size) { int newbytes; struct ip_set_req_ipmap_create *req = (struct ip_set_req_ipmap_create *) data; struct ip_set_ipmap *map; if (size != sizeof(struct ip_set_req_ipmap_create)) { ip_set_printk("data length wrong (want %zu, have %zu)", sizeof(struct ip_set_req_ipmap_create), size); return -EINVAL; } DP("from %u.%u.%u.%u to %u.%u.%u.%u", HIPQUAD(req->from), HIPQUAD(req->to)); if (req->from > req->to) { DP("bad ip range"); return -ENOEXEC; } map = kmalloc(sizeof(struct ip_set_ipmap), GFP_KERNEL); if (!map) { DP("out of memory for %d bytes", sizeof(struct ip_set_ipmap)); return -ENOMEM; } map->first_ip = req->from; map->last_ip = req->to; map->netmask = req->netmask; if (req->netmask == 0xFFFFFFFF) { map->hosts = 1; map->sizeid = map->last_ip - map->first_ip + 1; } else { unsigned int mask_bits, netmask_bits; ip_set_ip_t mask; map->first_ip &= map->netmask; /* Should we better bark? */ mask = range_to_mask(map->first_ip, map->last_ip, &mask_bits); netmask_bits = mask_to_bits(map->netmask); if ((!mask && (map->first_ip || map->last_ip != 0xFFFFFFFF)) || netmask_bits <= mask_bits) return -ENOEXEC; DP("mask_bits %u, netmask_bits %u", mask_bits, netmask_bits); map->hosts = 2 << (32 - netmask_bits - 1); map->sizeid = 2 << (netmask_bits - mask_bits - 1); } if (map->sizeid > MAX_RANGE + 1) { ip_set_printk("range too big (max %d addresses)", MAX_RANGE+1); kfree(map); return -ENOEXEC; } DP("hosts %u, sizeid %u", map->hosts, map->sizeid); newbytes = bitmap_bytes(0, map->sizeid - 1); map->members = kmalloc(newbytes, GFP_KERNEL); if (!map->members) { DP("out of memory for %d bytes", newbytes); kfree(map); return -ENOMEM; } memset(map->members, 0, newbytes); set->data = map; return 0; }
//start_listening void moon_listen(void) { //For test purposes moonraker_socket_t *listen; listen = kmalloc(sizeof(moonraker_socket_t),GFP_KERNEL); listen->proto = kmalloc(sizeof(moonraker_proto_t),GFP_KERNEL); listen->proto->name = kmalloc(5,GFP_KERNEL); listen->ip = 2130706433; listen->port = 80; listen->proto->defer_accept=0; listen->keepalive_timeout=0; listen->ack_pingpong=1; listen->max_backlog=2048; listen->defer_accept=1; strcpy(listen->proto->name,"http"); //end for test purpose struct sockaddr_in sin; struct socket *sock = NULL; struct sock *sk; struct tcp_sock *tp; struct inet_connection_sock *icsk; moonraker_proto_t *proto = listen->proto; u16 port = listen->port; u32 addr = listen->ip; //127.0.0.1 int err = 0; err = sock_create_kern(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock); if (err) { printk(KERN_ERR "Moonraker: error %d creating socket.\n", err); goto error; } sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(addr); sin.sin_port = htons(port); sk = sock->sk; icsk = inet_csk(sk); sk->sk_reuse = 1; sock_set_flag(sk, SOCK_URGINLINE); err = sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin)); if (err){ printk(KERN_ERR "Moonraker: error %d binding socket. This means that probably some other process is (or was a short time ago) using addr %d\n",err,sin.sin_addr.s_addr); goto error; } tp = tcp_sk(sk); printk("listen sk accept_queue: %d.\n",!reqsk_queue_empty(&icsk->icsk_accept_queue)); icsk->icsk_ack.pingpong = listen->ack_pingpong; sock_reset_flag(sk, SOCK_LINGER); sk->sk_lingertime = 0; tp->linger2 = listen->keepalive_timeout * HZ; if (proto->defer_accept && !listen->keepalive_timeout && listen->defer_accept) icsk->icsk_accept_queue.rskq_defer_accept = 1; err = sock->ops->listen(sock, listen->max_backlog); if (err) { printk(KERN_ERR "Moonraker: error %d listening on socket.\n", err); goto error; } printk(KERN_NOTICE "Moonraker: thread %d listens on %s://%d.%d.%d.%d:%d.\n", 1, proto->name, HIPQUAD(addr), port); // return sock; return; error: if (sock) sock_release(sock); return; return NULL; }
void print_skb_data(const char *msg, int count, struct sk_buff *skb, u8 *data, int len) { static int skb_count = 1000000; u8 *ptr, *end; u32 src_addr, dst_addr; // Transport layer header. union { struct tcphdr *th; struct udphdr *uh; struct icmphdr *icmph; struct igmphdr *igmph; struct iphdr *ipiph; unsigned char *raw; } h; // Network layer header. union { struct iphdr *iph; struct ipv6hdr *ipv6h; struct arpheader *arph; struct ipxhdr *ipxh; unsigned char *raw; } nh; // Link layer header. union { struct ethhdr *ethernet; unsigned char *raw; } mac; int protocol; if(!count) count = ++skb_count; if(!msg) msg = (char *)__FUNCTION__; if(!data){ printk("%s.%d> null data\n", msg, count); return; } ptr = data; end = data + len; mac.raw = ptr; ptr += sizeof(struct ethhdr); if(ptr > end){ printk("***MAC:"); goto exit; } protocol = ntohs(mac.ethernet->h_proto); nh.raw = ptr; printk("%s.%d> type=%d protocol=0x%x\n", msg, count, skb->pkt_type, htons(skb->protocol)); if(1){ printk("%s.%d> %p mac src=" MACFMT " dst=" MACFMT "\n", msg, count, data, MAC6TUPLE(mac.ethernet->h_source), MAC6TUPLE(mac.ethernet->h_dest)); } switch(protocol){ case ETH_P_ARP: ptr += sizeof(struct arpheader); if(ptr > end){ printk("***ARP:"); goto exit; } if(0){ printk("%s.%d> ARP hrd=%d, pro=%d, hln=%d, pln=%d, op=%d\n", msg, count, nh.arph->ar_hrd, nh.arph->ar_pro, nh.arph->ar_hln, nh.arph->ar_pln, nh.arph->ar_op); } memcpy(&src_addr, nh.arph->ar_sip, 4); src_addr = ntohl(src_addr); memcpy(&dst_addr, nh.arph->ar_tip, 4); dst_addr = ntohl(dst_addr); printk("%s.%d> ARP HW src=" MACFMT " dst=" MACFMT "\n", msg, count, MAC6TUPLE(nh.arph->ar_sha), MAC6TUPLE(nh.arph->ar_tha)); printk("%s.%d> ARP IP src=" IPFMT " dst=" IPFMT "\n", msg, count, HIPQUAD(src_addr), HIPQUAD(dst_addr)); break; case ETH_P_IP: { u16 src_port, dst_port; if(ptr + sizeof(struct iphdr) > end){ printk("***IP:"); goto exit; } src_addr = ntohl(nh.iph->saddr); dst_addr = ntohl(nh.iph->daddr); if(1){ printk("%s.%d> IP proto=%d src=" IPFMT " dst=" IPFMT "\n", msg, count, nh.iph->protocol, HIPQUAD(src_addr), HIPQUAD(dst_addr)); printk("%s.%d> IP tot_len=%u len=%d\n", msg, count, ntohs(nh.iph->tot_len), len - ETH_HLEN); } ptr += (nh.iph->ihl * 4); if(ptr > end){ printk ("***IP: len"); goto exit; } h.raw = ptr; switch(nh.iph->protocol){ case IPPROTO_TCP: ptr += sizeof(struct tcphdr); if(ptr > end){ printk("***TCP:"); goto exit; } src_port = ntohs(h.th->source); dst_port = ntohs(h.th->dest); printk("%s.%d> TCP src=" IPFMT ":%u dst=" IPFMT ":%u\n", msg, count, HIPQUAD(src_addr), src_port, HIPQUAD(dst_addr), dst_port); break; case IPPROTO_UDP: ptr += sizeof(struct udphdr); if(ptr > end){ printk("***UDP:"); goto exit; } src_port = ntohs(h.uh->source); dst_port = ntohs(h.uh->dest); printk("%s.%d> UDP src=" IPFMT ":%u dst=" IPFMT ":%u\n", msg, count, HIPQUAD(src_addr), src_port, HIPQUAD(dst_addr), dst_port); break; default: printk("%s.%d> IP %d src=" IPFMT " dst=" IPFMT "\n", msg, count, nh.iph->protocol, HIPQUAD(src_addr), HIPQUAD(dst_addr)); break; } break; } case ETH_P_IPV6: printk("%s.%d> IPv6\n", msg, count); break; case ETH_P_IPX: printk("%s.%d> IPX\n", msg, count); break; default: printk("%s.%d> protocol=%d\n", msg, count, protocol); break; } return; exit: printk("%s.%d> %s: skb problem\n", msg, count, __FUNCTION__); printk("%s.%d> %s: data=%p end=%p(%d) ptr=%p(%d) eth=%d ip=%d\n", msg, count, __FUNCTION__, data, end, end - data, ptr, ptr - data, sizeof(struct ethhdr), sizeof(struct iphdr)); return; }
static void isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb) { isdn_net_local *mlp = idev->mlp; struct inl_cisco *cisco = mlp->inl_priv; unsigned char *p; int period; u32 code; u32 my_seq, addr; u32 your_seq, mask; u32 local; u16 unused; if (skb->len < 14) return; p = skb->data; p += get_u32(p, &code); switch (code) { case CISCO_SLARP_REQUEST: cisco->yourseq = 0; isdn_net_ciscohdlck_slarp_send_reply(idev); break; case CISCO_SLARP_REPLY: addr = ntohl(*(u32 *)p); mask = ntohl(*(u32 *)(p+4)); if (mask != 0xfffffffc) goto slarp_reply_out; if ((addr & 3) == 0 || (addr & 3) == 3) goto slarp_reply_out; local = addr ^ 3; printk(KERN_INFO "%s: got slarp reply: " "remote ip: %d.%d.%d.%d, " "local ip: %d.%d.%d.%d " "mask: %d.%d.%d.%d\n", idev->name, HIPQUAD(addr), HIPQUAD(local), HIPQUAD(mask)); break; slarp_reply_out: printk(KERN_INFO "%s: got invalid slarp " "reply (%d.%d.%d.%d/%d.%d.%d.%d) " "- ignored\n", idev->name, HIPQUAD(addr), HIPQUAD(mask)); break; case CISCO_SLARP_KEEPALIVE: period = (jiffies - cisco->last_slarp_in + HZ/2 - 1) / HZ; if (cisco->debserint && (period != cisco->keepalive_period) && cisco->last_slarp_in) { printk(KERN_DEBUG "%s: Keepalive period mismatch - " "is %d but should be %d.\n", idev->name, period, cisco->keepalive_period); } cisco->last_slarp_in = jiffies; p += get_u32(p, &my_seq); p += get_u32(p, &your_seq); p += get_u16(p, &unused); cisco->yourseq = my_seq; cisco->mineseen = your_seq; break; } }