コード例 #1
0
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);
}
コード例 #2
0
/*
 * 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--;
      }
}
コード例 #3
0
ファイル: l2tp_proto.c プロジェクト: TARRANUM/ppp
/* -----------------------------------------------------------------------------
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;
}
コード例 #4
0
ファイル: ip6_mroute.c プロジェクト: orumin/openbsd-efivars
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;
}
コード例 #5
0
ファイル: idp_usrreq.c プロジェクト: NKSG/INTER_MANET_NS3
/*
 *  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);
}
コード例 #6
0
ファイル: ipx_usrreq.c プロジェクト: ChaosJohn/freebsd
/*
 *  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);
}
コード例 #7
0
ファイル: ng_socket.c プロジェクト: wan721/DragonFlyBSD
/*
 * 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);
}
コード例 #8
0
ファイル: keysock.c プロジェクト: MarginC/kame
/*
 * 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);
}
コード例 #9
0
ファイル: ng_socket.c プロジェクト: wan721/DragonFlyBSD
/*
 * 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);
}
コード例 #10
0
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;
}
コード例 #11
0
ファイル: rawsock.c プロジェクト: fjanssen/Car2X
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;
}
コード例 #12
0
ファイル: ip_divert.c プロジェクト: UnitedMarsupials/kame
/*
 * 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--;
        }
}
コード例 #13
0
ファイル: lpx_usrreq.c プロジェクト: dansdrivers/ndas4mac
/*
 *  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);
}
コード例 #14
0
ファイル: ps_socket.c プロジェクト: srcman/blackhawk
/*
 * 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;
}
コード例 #15
0
ファイル: lpx_datagram.c プロジェクト: dansdrivers/ndas4mac
/*
 *  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);
}