int STKARGFUN raw_input(struct mbuf *m0, struct sockproto *proto, struct sockaddr *src, struct sockaddr *dst) { register struct rawcb *rp; register struct mbuf *m = m0; register int sockets = 0; struct socket *last; last = 0; for (rp = rawcb.rcb_next; rp != &rawcb; rp = rp->rcb_next) { if (rp->rcb_proto.sp_family != proto->sp_family) continue; if (rp->rcb_proto.sp_protocol && rp->rcb_proto.sp_protocol != proto->sp_protocol) continue; /* * We assume the lower level routines have * placed the address in a canonical format * suitable for a structure comparison. * * Note that if the lengths are not the same * the comparison will fail at the first byte. */ #define equal(a1, a2) \ (bcmp((caddr_t)(a1), (caddr_t)(a2), a1->sa_len) == 0) if (rp->rcb_laddr && !equal(rp->rcb_laddr, dst)) continue; if (rp->rcb_faddr && !equal(rp->rcb_faddr, src)) continue; if (last) { struct mbuf *n; if (n = m_copy(m, 0, (int)M_COPYALL)) { if (sbappendaddr(&last->so_rcv, src, n, (struct mbuf *)0) == 0) /* should notify about lost packet */ m_freem(n); else { sorwakeup(last); sockets++; } } } last = rp->rcb_socket; } if (last) { if (sbappendaddr(&last->so_rcv, src, m, (struct mbuf *)0) == 0) m_freem(m); else { sorwakeup(last); sockets++; } } else m_freem(m); return (sockets); }
/* * Setup generic address and protocol structures * for raw_input routine, then pass them along with * mbuf chain. */ void rip_input(struct mbuf *m, int iphlen) { struct ip *ip = mtod(m, struct ip *); register struct inpcb *inp; struct inpcb *last = 0; struct mbuf *opts = 0; ripsrc.sin_addr = ip->ip_src; for (inp = ripcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { if (inp->inp_ip_p && inp->inp_ip_p != ip->ip_p) continue; if (inp->inp_laddr.s_addr && inp->inp_laddr.s_addr != ip->ip_dst.s_addr) continue; if (inp->inp_faddr.s_addr && inp->inp_faddr.s_addr != ip->ip_src.s_addr) continue; if (last) { struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); if (n) { if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(last, &opts, ip, n); if (sbappendaddr(&last->inp_socket->so_rcv, (struct sockaddr *)&ripsrc, n, opts) == 0) { /* should notify about lost packet */ m_freem(n); if (opts) m_freem(opts); } else sorwakeup(last->inp_socket); opts = 0; } } last = inp; } if (last) { if (last->inp_flags & INP_CONTROLOPTS || last->inp_socket->so_options & SO_TIMESTAMP) ip_savecontrol(last, &opts, ip, m); if (sbappendaddr(&last->inp_socket->so_rcv, (struct sockaddr *)&ripsrc, m, opts) == 0) { m_freem(m); if (opts) m_freem(opts); } else sorwakeup(last->inp_socket); } else { m_freem(m); ipstat.ips_noproto++; ipstat.ips_delivered--; } }
/* ----------------------------------------------------------------------------- called from l2tp_rfc when data are present ----------------------------------------------------------------------------- */ int l2tp_input(void *data, mbuf_t m, struct sockaddr *from, int more) { struct socket *so = (struct socket *)data; int err; lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED); if (so->so_tpcb) { // we are hooked to ppp return l2tp_wan_input(ALIGNED_CAST(struct ppp_link *)so->so_tpcb, m); // Wcast-align fix - we malloc so->so_tpcb } if (m) { if (from == 0) { // no from address, just free the buffer mbuf_freem(m); return 1; } if (sbappendaddr(&so->so_rcv, from, (struct mbuf *)m, 0, &err) == 0) { //IOLog("l2tp_input no space, so = %p\n", so); return 1; } } if (!more) sorwakeup(so); return 0; }
int socket6_send(struct socket *s, struct mbuf *mm, struct sockaddr_in6 *src) { if (s) { if (sbappendaddr(&s->so_rcv, sin6tosa(src), mm, NULL) != 0) { sorwakeup(s); return 0; } } m_freem(mm); return -1; }
/* * This may also be called for raw listeners. */ void idp_input(struct mbuf *m, ...) { struct nspcb *nsp; struct idp *idp = mtod(m, struct idp *); struct ifnet *ifp = m->m_pkthdr.rcvif; struct sockaddr_ns idp_ns; va_list ap; va_start(ap, m); nsp = va_arg(ap, struct nspcb *); va_end(ap); if (nsp == NULL) panic("No nspcb"); /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ bzero(&idp_ns, sizeof(idp_ns)); idp_ns.sns_len = sizeof(idp_ns); idp_ns.sns_family = AF_NS; idp_ns.sns_addr = idp->idp_sna; if (ns_neteqnn(idp->idp_sna.x_net, ns_zeronet) && ifp) { struct ifaddr *ifa; for (ifa = ifp->if_addrlist.tqh_first; ifa != 0; ifa = ifa->ifa_list.tqe_next) { if (ifa->ifa_addr->sa_family == AF_NS) { idp_ns.sns_addr.x_net = IA_SNS(ifa)->sns_addr.x_net; break; } } } nsp->nsp_rpt = idp->idp_pt; if ( ! (nsp->nsp_flags & NSP_RAWIN) ) { m->m_len -= sizeof (struct idp); m->m_pkthdr.len -= sizeof (struct idp); m->m_data += sizeof (struct idp); } if (sbappendaddr(&nsp->nsp_socket->so_rcv, snstosa(&idp_ns), m, (struct mbuf *)0) == 0) goto bad; sorwakeup(nsp->nsp_socket); return; bad: m_freem(m); }
/* * This may also be called for raw listeners. */ void ipx_input(struct mbuf *m, struct ipxpcb *ipxp) { struct ipx *ipx = mtod(m, struct ipx *); struct ifnet *ifp = m->m_pkthdr.rcvif; struct sockaddr_ipx ipx_ipx; KASSERT(ipxp != NULL, ("ipx_input: NULL ipxpcb")); IPX_LOCK_ASSERT(ipxp); /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ ipx_ipx.sipx_len = sizeof(ipx_ipx); ipx_ipx.sipx_family = AF_IPX; ipx_ipx.sipx_addr = ipx->ipx_sna; ipx_ipx.sipx_zero[0] = '\0'; ipx_ipx.sipx_zero[1] = '\0'; if (ipx_neteqnn(ipx->ipx_sna.x_net, ipx_zeronet) && ifp != NULL) { struct ifaddr *ifa; for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_link)) { if (ifa->ifa_addr->sa_family == AF_IPX) { ipx_ipx.sipx_addr.x_net = IA_SIPX(ifa)->sipx_addr.x_net; break; } } } ipxp->ipxp_rpt = ipx->ipx_pt; if ((ipxp->ipxp_flags & IPXP_RAWIN) == 0) { m->m_len -= sizeof(struct ipx); m->m_pkthdr.len -= sizeof(struct ipx); m->m_data += sizeof(struct ipx); } #ifdef MAC if (mac_socket_check_deliver(ipxp->ipxp_socket, m) != 0) { m_freem(m); return; } #endif if (sbappendaddr(&ipxp->ipxp_socket->so_rcv, (struct sockaddr *)&ipx_ipx, m, NULL) == 0) m_freem(m); else sorwakeup(ipxp->ipxp_socket); }
/* * Receive data on a hook */ static int ngs_rcvdata(hook_p hook, item_p item) { struct ngsock *const priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); struct ngpcb *const pcbp = priv->datasock; struct socket *so; struct sockaddr_ng *addr; char *addrbuf[NG_HOOKSIZ + 4]; int addrlen; struct mbuf *m; NGI_GET_M(item, m); NG_FREE_ITEM(item); /* If there is no data socket, black-hole it. */ if (pcbp == NULL) { NG_FREE_M(m); return (0); } so = pcbp->ng_socket; /* Get the return address into a sockaddr. */ addrlen = strlen(NG_HOOK_NAME(hook)); /* <= NG_HOOKSIZ - 1 */ addr = (struct sockaddr_ng *) addrbuf; addr->sg_len = addrlen + 3; addr->sg_family = AF_NETGRAPH; bcopy(NG_HOOK_NAME(hook), addr->sg_data, addrlen); addr->sg_data[addrlen] = '\0'; /* Try to tell the socket which hook it came in on. */ if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)addr, m, NULL) == 0) { m_freem(m); TRAP_ERROR; return (ENOBUFS); } sorwakeup(so); return (0); }
/* * send message to the socket. */ static int key_sendup0(struct rawcb *rp, struct mbuf *m, int promisc, int canwait) { struct keycb *kp = (struct keycb *)rp; struct mbuf *n; int error = 0; if (canwait) { if (kp->kp_queue) { for (n = kp->kp_queue; n && n->m_nextpkt; n = n->m_nextpkt) ; n->m_nextpkt = m; m = kp->kp_queue; kp->kp_queue = NULL; } else m->m_nextpkt = NULL; /* just for safety */ } else m->m_nextpkt = NULL; for (; m && error == 0; m = n) { n = m->m_nextpkt; if (promisc) { struct sadb_msg *pmsg; M_PREPEND(m, sizeof(struct sadb_msg), M_NOWAIT); if (m && m->m_len < sizeof(struct sadb_msg)) m = m_pullup(m, sizeof(struct sadb_msg)); if (!m) { pfkeystat.in_nomem++; error = ENOBUFS; goto recovery; } m->m_pkthdr.len += sizeof(*pmsg); pmsg = mtod(m, struct sadb_msg *); bzero(pmsg, sizeof(*pmsg)); pmsg->sadb_msg_version = PF_KEY_V2; pmsg->sadb_msg_type = SADB_X_PROMISC; pmsg->sadb_msg_len = PFKEY_UNIT64(m->m_pkthdr.len); /* pid and seq? */ pfkeystat.in_msgtype[pmsg->sadb_msg_type]++; } if (canwait && sbspace(&rp->rcb_socket->so_rcv) < m->m_pkthdr.len) { error = EAGAIN; goto recovery; } m->m_nextpkt = NULL; if (!sbappendaddr(&rp->rcb_socket->so_rcv, (struct sockaddr *)&key_src, m, NULL)) { pfkeystat.in_nomem++; error = ENOBUFS; goto recovery; } else { sorwakeup(rp->rcb_socket); error = 0; } } return (error); recovery: if (kp->kp_queue) { /* * insert m to the head of queue, as normally mbuf on the queue * is less important than others. */ if (m) { m->m_nextpkt = kp->kp_queue; kp->kp_queue = m; } } else { /* recover the queue */ if (!m) { /* first ENOBUFS case */ kp->kp_queue = n; } else { kp->kp_queue = m; m->m_nextpkt = n; } } return (error); }
/* * Incoming messages get passed up to the control socket. * Unless they are for us specifically (socket_type) */ static int ngs_rcvmsg(node_p node, item_p item, hook_p lasthook) { struct ngsock *const priv = NG_NODE_PRIVATE(node); struct ngpcb *const pcbp = priv->ctlsock; struct socket *so; struct sockaddr_ng addr; struct ng_mesg *msg; struct mbuf *m; ng_ID_t retaddr = NGI_RETADDR(item); int addrlen; int error = 0; NGI_GET_MSG(item, msg); NG_FREE_ITEM(item); /* * Only allow mesgs to be passed if we have the control socket. * Data sockets can only support the generic messages. */ if (pcbp == NULL) { TRAP_ERROR; NG_FREE_MSG(msg); return (EINVAL); } so = pcbp->ng_socket; #ifdef TRACE_MESSAGES kprintf("[%x]:---------->[socket]: c=<%d>cmd=%x(%s) f=%x #%d\n", retaddr, msg->header.typecookie, msg->header.cmd, msg->header.cmdstr, msg->header.flags, msg->header.token); #endif if (msg->header.typecookie == NGM_SOCKET_COOKIE) { switch (msg->header.cmd) { case NGM_SOCK_CMD_NOLINGER: priv->flags |= NGS_FLAG_NOLINGER; break; case NGM_SOCK_CMD_LINGER: priv->flags &= ~NGS_FLAG_NOLINGER; break; default: error = EINVAL; /* unknown command */ } /* Free the message and return. */ NG_FREE_MSG(msg); return (error); } /* Get the return address into a sockaddr. */ bzero(&addr, sizeof(addr)); addr.sg_len = sizeof(addr); addr.sg_family = AF_NETGRAPH; addrlen = ksnprintf((char *)&addr.sg_data, sizeof(addr.sg_data), "[%x]:", retaddr); if (addrlen < 0 || addrlen > sizeof(addr.sg_data)) { kprintf("%s: ksnprintf([%x]) failed - %d\n", __func__, retaddr, addrlen); NG_FREE_MSG(msg); return (EINVAL); } /* Copy the message itself into an mbuf chain. */ m = m_devget((caddr_t)msg, sizeof(struct ng_mesg) + msg->header.arglen, 0, NULL, NULL); /* * Here we free the message. We need to do that * regardless of whether we got mbufs. */ NG_FREE_MSG(msg); if (m == NULL) { TRAP_ERROR; return (ENOBUFS); } /* Send it up to the socket. */ if (sbappendaddr((struct sockbuf *)&so->so_rcv, (struct sockaddr *)&addr, m, NULL) == 0) { TRAP_ERROR; m_freem(m); return (ENOBUFS); } sorwakeup(so); return (error); }
static int uipc_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, struct mbuf *control, struct proc *p) { int error = 0; struct unpcb *unp = sotounpcb(so); struct socket *so2; u_long newhiwat; if (unp == 0) { error = EINVAL; goto release; } if (flags & PRUS_OOB) { error = EOPNOTSUPP; goto release; } if (control && (error = unp_internalize(control, p))) goto release; switch (so->so_type) { case SOCK_DGRAM: { struct sockaddr *from; if (nam) { if (unp->unp_conn) { error = EISCONN; break; } error = unp_connect(so, nam, p); if (error) break; } else { if (unp->unp_conn == 0) { error = ENOTCONN; break; } } so2 = unp->unp_conn->unp_socket; if (unp->unp_addr) from = (struct sockaddr *)unp->unp_addr; else from = &sun_noname; if (sbappendaddr(&so2->so_rcv, from, m, control)) { sorwakeup(so2); m = 0; control = 0; } else error = ENOBUFS; if (nam) unp_disconnect(unp); break; } case SOCK_STREAM: /* Connect if not connected yet. */ /* * Note: A better implementation would complain * if not equal to the peer's address. */ if ((so->so_state & SS_ISCONNECTED) == 0) { if (nam) { error = unp_connect(so, nam, p); if (error) break; /* XXX */ } else { error = ENOTCONN; break; } } if (so->so_state & SS_CANTSENDMORE) { error = EPIPE; break; } if (unp->unp_conn == 0) panic("uipc_send connected but no connection?"); so2 = unp->unp_conn->unp_socket; /* * Send to paired receive port, and then reduce * send buffer hiwater marks to maintain backpressure. * Wake up readers. */ if (control) { if (sbappendcontrol(&so2->so_rcv, m, control)) control = 0; } else sbappend(&so2->so_rcv, m); so->so_snd.sb_mbmax -= so2->so_rcv.sb_mbcnt - unp->unp_conn->unp_mbcnt; unp->unp_conn->unp_mbcnt = so2->so_rcv.sb_mbcnt; newhiwat = so->so_snd.sb_hiwat - (so2->so_rcv.sb_cc - unp->unp_conn->unp_cc); (void)chgsbsize(so->so_cred->cr_uidinfo, &so->so_snd.sb_hiwat, newhiwat, RLIM_INFINITY); unp->unp_conn->unp_cc = so2->so_rcv.sb_cc; sorwakeup(so2); m = 0; break; default: panic("uipc_send unknown socktype"); } /* * SEND_EOF is equivalent to a SEND followed by * a SHUTDOWN. */ if (flags & PRUS_EOF) { socantsendmore(so); unp_shutdown(unp); } if (control && error != 0) unp_dispose(control); release: if (control) m_freem(control); if (m) m_freem(m); return error; }
int rawip_soinput(PACKET pkt, void * so_ptr) { struct mbuf * m_in; /* packet/data mbuf */ struct socket * so = (struct socket *)so_ptr; struct sockaddr_in sin; LOCK_NET_RESOURCE(NET_RESID); /* make sure we're not flooding input buffers */ if ((so->so_rcv.sb_cc + pkt->nb_plen) >= so->so_rcv.sb_hiwat) { UNLOCK_NET_RESOURCE(NET_RESID); return ENOBUFS; } /* alloc mbuf for received data */ m_in = m_getnbuf(MT_RXDATA, 0); if (!m_in) { UNLOCK_NET_RESOURCE(NET_RESID); return ENOBUFS; } /* set data mbuf to point to start of IP header */ m_in->pkt = pkt; m_in->m_base = pkt->nb_buff; m_in->m_memsz = pkt->nb_blen; m_in->m_data = pkt->nb_prot; m_in->m_len = pkt->nb_plen; /* if this socket doesn't have IP_HDRINCL set, adjust the * mbuf to skip past the IP header */ if (!(so->so_options & SO_HDRINCL)) { unsigned int ihl = (((struct ip *)(pkt->nb_prot))->ip_ver_ihl & 0x0f) << 2; m_in->m_data += ihl; m_in->m_len -= ihl; } /* fill in net address info for pass to socket append()ers */ sin.sin_addr.s_addr = pkt->fhost; sin.sin_port = 0; sin.sin_family = AF_INET; /* attempt to append address information to mbuf */ if (!sbappendaddr(&so->so_rcv, (struct sockaddr *)&sin, m_in)) { /* set the pkt field in the mbuf to NULL so m_free() below wont * free the packet buffer, because that is left to the * underlying stack */ m_in->pkt = NULL; /* free only the mbuf itself */ m_free(m_in); /* return error condition so caller can free the packet buffer */ UNLOCK_NET_RESOURCE(NET_RESID); return ENOBUFS; } tcp_wakeup(&so->so_rcv); /* wake anyone waiting for this */ sorwakeup(so); /* wake up selects too */ UNLOCK_NET_RESOURCE(NET_RESID); return 0; }
/* * Setup generic address and protocol structures * for div_input routine, then pass them along with * mbuf chain. ip->ip_len is assumed to have had * the header length (hlen) subtracted out already. * We tell whether the packet was incoming or outgoing * by seeing if hlen == 0, which is a hack. */ void div_input(struct mbuf *m, int off, int proto) { int hlen = off; struct ip *ip; struct inpcb *inp; struct socket *sa; /* Sanity check */ if (ip_divert_port == 0) panic("div_input: port is 0"); /* Assure header */ if (m->m_len < sizeof(struct ip) && (m = m_pullup(m, sizeof(struct ip))) == 0) { return; } ip = mtod(m, struct ip *); /* Record divert cookie */ divsrc.sin_port = ip_divert_cookie; ip_divert_cookie = 0; /* Restore packet header fields */ ip->ip_len += hlen; HTONS(ip->ip_len); HTONS(ip->ip_off); /* * Record receive interface address, if any * But only for incoming packets. */ divsrc.sin_addr.s_addr = 0; if (hlen) { struct ifaddr *ifa; #ifdef DIAGNOSTIC /* Sanity check */ if (!(m->m_flags & M_PKTHDR)) panic("div_input: no pkt hdr"); #endif /* More fields affected by ip_input() */ HTONS(ip->ip_id); /* Find IP address for recieve interface */ for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa != NULL; ifa = ifa->ifa_next) { if (ifa->ifa_addr == NULL) continue; if (ifa->ifa_addr->sa_family != AF_INET) continue; divsrc.sin_addr = ((struct sockaddr_in *) ifa->ifa_addr)->sin_addr; break; } } /* * Record the incoming interface name whenever we have one. */ if (m->m_pkthdr.rcvif) { char name[32]; /* * Hide the actual interface name in there in the * sin_zero array. XXX This needs to be moved to a * different sockaddr type for divert, e.g. * sockaddr_div with multiple fields like * sockaddr_dl. Presently we have only 7 bytes * but that will do for now as most interfaces * are 4 or less + 2 or less bytes for unit. * There is probably a faster way of doing this, * possibly taking it from the sockaddr_dl on the iface. * This solves the problem of a P2P link and a LAN interface * having the same address, which can result in the wrong * interface being assigned to the packet when fed back * into the divert socket. Theoretically if the daemon saves * and re-uses the sockaddr_in as suggested in the man pages, * this iface name will come along for the ride. * (see div_output for the other half of this.) */ sprintf(name, "%s%d", m->m_pkthdr.rcvif->if_name, m->m_pkthdr.rcvif->if_unit); strncpy(divsrc.sin_zero, name, 7); } /* Put packet on socket queue, if any */ sa = NULL; for (inp = divcb.lh_first; inp != NULL; inp = inp->inp_list.le_next) { if (inp->inp_lport == htons(ip_divert_port)) sa = inp->inp_socket; } ip_divert_port = 0; if (sa) { if (sbappendaddr(&sa->so_rcv, (struct sockaddr *)&divsrc, m, (struct mbuf *)0) == 0) m_freem(m); else sorwakeup(sa); } else { m_freem(m); ipstat.ips_noproto++; ipstat.ips_delivered--; } }
/* * This may also be called for raw listeners. */ void Lpx_USER_input( struct mbuf *m, register struct lpxpcb *lpxp, struct ether_header *frame_header) { register struct lpxhdr *lpxh = mtod(m, struct lpxhdr *); // struct ifnet *ifp = m->m_pkthdr.rcvif; struct sockaddr_lpx lpx_lpx; struct ether_header *eh; // struct lpx_addr sna_addr; #if 0 eh = (struct ether_header *) m->m_pktdat; #else /* if 0 */ eh = frame_header; #endif /* if 0 else */ DEBUG_CALL(4, ("Lpx_USER_input\n")); #if 0 { int iter=0; DEBUG_CALL(6,("Lpx_USER_input:")); for (iter=0; iter<16; iter++) { DEBUG_CALL(6,(" %02x",((char*)eh)[iter])); } DEBUG_CALL(6,("\n")); } #endif /* if 0 */ if (lpxp == NULL) panic("No lpxpcb"); /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ bzero(&lpx_lpx, sizeof(lpx_lpx)); lpx_lpx.slpx_len = sizeof(lpx_lpx); lpx_lpx.slpx_family = AF_LPX; bcopy(eh->ether_shost, lpx_lpx.slpx_node, LPX_NODE_LEN); lpx_lpx.slpx_port = lpxh->source_port; DEBUG_CALL(6,("Lpx_USER_input: %02x:%02x:%02x:%02x:%02x:%02x:%d\n", eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2], eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5], lpxh->source_port)); DEBUG_CALL(6,("Lpx_USER_input: %02x:%02x:%02x:%02x:%02x:%02x:%d\n", lpx_lpx.slpx_node[0], lpx_lpx.slpx_node[1], lpx_lpx.slpx_node[2], lpx_lpx.slpx_node[3], lpx_lpx.slpx_node[4], lpx_lpx.slpx_node[5], lpx_lpx.slpx_port)); #if 0 if (lpx_neteqnn(lpx->lpx_sna.x_net, lpx_zeronet) && ifp != NULL) { register struct ifaddr *ifa; for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa != NULL; ifa = TAILQ_NEXT(ifa, ifa_link)) { if (ifa->ifa_addr->sa_family == AF_LPX) { lpx_lpx.sipx_addr.x_net = IA_SLPX(ifa)->sipx_addr.x_net; break; } } } #endif // lpxp->lpxp_rpt = lpx->lpx_pt; if (!(lpxp->lpxp_flags & LPXP_RAWIN) ) { m_adj(m, sizeof(struct lpxhdr)); // m->m_len -= sizeof(struct lpxhdr); // m->m_pkthdr.len -= sizeof(struct lpxhdr); // m->m_data += sizeof(struct lpxhdr); } if (sbappendaddr(&lpxp->lpxp_socket->so_rcv, (struct sockaddr *)&lpx_lpx, m, (struct mbuf *)NULL) == 0) { DEBUG_CALL(2, ("!!!Lpx_USER_input: sbappendaddr error: socket=@(%lx), rcv@(%lx)!",lpxp->lpxp_socket, &(lpxp->lpxp_socket->so_rcv))); goto bad; } // m->m_len += sizeof(struct sockaddr); // m->m_pkthdr.len += sizeof(struct sockaddr); // m->m_data -= sizeof(struct sockaddr); DEBUG_CALL(4, ("Lpx_USER_input: socket sbflag=%x\n",lpxp->lpxp_socket->so_rcv.sb_flags)); #if 1 sorwakeup(lpxp->lpxp_socket); DEBUG_CALL(4, ("Lpx_USER_input: wokeup socket @(%lx)\n",lpxp->lpxp_socket)); #else /* if 0 */ if (lpxp->lpxp_socket->so_rcv.sb_flags & (SB_WAIT|SB_SEL|SB_ASYNC|SB_UPCALL)) { DEBUG_CALL(4, ("Lpx_USER_input: sowokeup socket @(%lx)\n",lpxp->lpxp_socket)); sowakeup(lpxp->lpxp_socket, &lpxp->lpxp_socket->so_rcv); } #endif /* if 0 else */ return; bad: m_freem(m); }
/* * Caveat: Called from interrupt context */ static void ps_ether_input(struct ifnet *ifp, struct mbuf **mp) { struct pspcb *psp = NULL, *psp_next; struct ether_header *eh; struct sockaddr esa; struct socket *so = NULL; u_short etype; eh = mtod(*mp, struct ether_header *); etype = ntohs(eh->ether_type); if (PS_ETHER_TYPE != etype) return; /* * We currently place the mbuf to a bound socket's rcv. * * However,this is not the long term plan. Instead, in the * longer term we should fill in a page, place the page at * the local cache, and then wake up the network receiver. * through the bound socket. */ PS_PRINTF(PS_DEBUG_SOCKET, "m = %p\n", *mp); LIST_FOREACH_SAFE(psp, pspcbhead, psp_list, psp_next) { #if __FreeBSD_version >= 701000 if (!rw_try_rlock(&psp->psp_lock)) { PS_PRINTF(PS_DEBUG_SOCKET | PS_DEBUG_WARNING, "psp is w-locked, discard data\n"); /* Simply discard data if the psp happens to be w-locked */ continue; } #endif if (ifp == psp->psp_ifp) { so = psp->psp_socket; #if __FreeBSD_version >= 701000 rw_runlock(&psp->psp_lock); #endif break; } #if __FreeBSD_version >= 701000 rw_runlock(&psp->psp_lock); #endif } if (so) { /* * XXX: We don't understand why simple sbappend * doesn't work. But spappendaddr does. So be it. */ esa.sa_family = AF_LINK; esa.sa_len = 0; m_adj(*mp, sizeof(*eh)); /* Remove ethernet header */ if (!sbappendaddr(&so->so_rcv, &esa, *mp, NULL)) { PS_PRINTF(PS_DEBUG_SOCKET | PS_DEBUG_WARNING, "sbappendaddr() failed. " "Probably not enough buffer space. " "Packet lost.\n"); } sorwakeup(so); *mp = NULL; return; } #ifdef NOTYET /* We could free *mp here, but we don't. It gets discarded anyway */ m_freem(*mp); *mp = NULL; #endif return; }
/* * This may also be called for raw listeners. */ void lpx_datagram_input( struct mbuf *m, register struct lpxpcb *lpxp, struct ether_header *frame_header) { register struct lpxhdr *lpxh = mtod(m, struct lpxhdr *); // struct ifnet *ifp = m->m_pkthdr.rcvif; struct sockaddr_lpx lpx_lpx; struct ether_header *eh; // struct lpx_addr sna_addr; int error; eh = frame_header; DEBUG_PRINT(DEBUG_MASK_DGRAM_TRACE, ("Lpx_USER_datagram_input: Entered\n")); if (lpxp == NULL) panic("Lpx_USER_datagram_input: No lpxpcb"); /* DEBUG_PRINT(DEBUG_MASK_DGRAM_INFO, ("Lpx_USER_datagram_input: D Port 0x%x, S Port 0x%x\n", ntohs(lpxh->dest_port), ntohs(lpxh->source_port) )); DEBUG_PRINT(DEBUG_MASK_DGRAM_INFO, ("Lpx_USER_datagram_input: Message ID : 0x%x, Total Length : 0x%x, Frag ID : 0x%x, Frag Length : 0x%x\n", ntohs(lpxh->u.d.message_id), ntohs(lpxh->u.d.message_length), ntohs(lpxh->u.d.fragment_id), ntohs(lpxh->u.d.frament_length) )); */ /* * Construct sockaddr format source address. * Stuff source address and datagram in user buffer. */ bzero(&lpx_lpx, sizeof(lpx_lpx)); lpx_lpx.slpx_len = sizeof(lpx_lpx); lpx_lpx.slpx_family = AF_LPX; bcopy(eh->ether_shost, lpx_lpx.slpx_node, LPX_NODE_LEN); lpx_lpx.slpx_port = lpxh->source_port; /* DEBUG_PRINT(DEBUG_MASK_DGRAM_INFO, ("Lpx_USER_datagram_input: %02x:%02x:%02x:%02x:%02x:%02x:%d\n", eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2], eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5], lpxh->source_port)); DEBUG_PRINT(DEBUG_MASK_DGRAM_INFO, ("Lpx_USER_datagram_input: %02x:%02x:%02x:%02x:%02x:%02x:%d\n", lpx_lpx.slpx_node[0], lpx_lpx.slpx_node[1], lpx_lpx.slpx_node[2], lpx_lpx.slpx_node[3], lpx_lpx.slpx_node[4], lpx_lpx.slpx_node[5], lpx_lpx.slpx_port)); */ // Remove Lpx Header. m_adj(m, sizeof(struct lpxhdr)); // Drop Bad Packet. if (m->m_len < ntohs(lpxh->u.d.message_length)) { goto bad; } // Trim data. if (m->m_len > ntohs(lpxh->u.d.message_length)) { m_adj(m, - (m->m_len - ntohs(lpxh->u.d.message_length))); } if (sbappendaddr(&lpxp->lpxp_socket->so_rcv, (struct sockaddr *)&lpx_lpx, m, (struct mbuf *)NULL, &error) == 0) { DEBUG_PRINT(DEBUG_MASK_DGRAM_WARING, ("Lpx_USER_input: Maybe No space for this packet. sbappendaddr error: socket=@(%lx), rcv@(%lx)!",lpxp->lpxp_socket, &(lpxp->lpxp_socket->so_rcv))); // sbappendaddr() free m when the error occured. } else { // m->m_len += sizeof(struct sockaddr); // m->m_pkthdr.len += sizeof(struct sockaddr); // m->m_data -= sizeof(struct sockaddr); DEBUG_PRINT(DEBUG_MASK_DGRAM_INFO, ("Lpx_USER_input: socket sbflag=%x\n",lpxp->lpxp_socket->so_rcv.sb_flags)); sorwakeup(lpxp->lpxp_socket); DEBUG_PRINT(DEBUG_MASK_DGRAM_INFO, ("Lpx_USER_input: wokeup socket @(%lx)\n",lpxp->lpxp_socket)); } return; bad: m_freem(m); }