コード例 #1
0
void
soisconnected(struct socket *so)
{
	struct socket	*head;

	head = so->so_head;

	KASSERT(solocked(so));
	KASSERT(head == NULL || solocked2(so, head));

	so->so_state &= ~(SS_ISCONNECTING | SS_ISDISCONNECTING);
	so->so_state |= SS_ISCONNECTED;
	if (head && so->so_onq == &head->so_q0) {
		if ((so->so_options & SO_ACCEPTFILTER) == 0) {
			soqremque(so, 0);
			soqinsque(head, so, 1);
			sorwakeup(head);
			cv_broadcast(&head->so_cv);
		} else {
			so->so_upcall =
			    head->so_accf->so_accept_filter->accf_callback;
			so->so_upcallarg = head->so_accf->so_accept_filter_arg;
			so->so_rcv.sb_flags |= SB_UPCALL;
			so->so_options &= ~SO_ACCEPTFILTER;
			(*so->so_upcall)(so, so->so_upcallarg,
					 POLLIN|POLLRDNORM, M_DONTWAIT);
		}
	} else {
		cv_broadcast(&so->so_cv);
		sorwakeup(so);
		sowwakeup(so);
	}
}
コード例 #2
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);
}
コード例 #3
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--;
      }
}
コード例 #4
0
ファイル: uipc_socket2.c プロジェクト: ajinkya93/OpenBSD
void
socantrcvmore(struct socket *so)
{

	so->so_state |= SS_CANTRCVMORE;
	sorwakeup(so);
}
コード例 #5
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;
}
コード例 #6
0
ファイル: udp_usrreq.c プロジェクト: iHaD/DragonFlyBSD
/*
 * Notify a udp user of an asynchronous error;
 * just wake up so that he can collect error status.
 */
void
udp_notify(struct inpcb *inp, int error)
{
	inp->inp_socket->so_error = error;
	sorwakeup(inp->inp_socket);
	sowwakeup(inp->inp_socket);
}
コード例 #7
0
ファイル: udp_usrreq.c プロジェクト: iHaD/DragonFlyBSD
/*
 * subroutine of udp_input(), mainly for source code readability.
 * caller must properly init udp_ip6 and udp_in6 beforehand.
 */
static void
udp_append(struct inpcb *last, struct ip *ip, struct mbuf *n, int off,
    struct sockaddr_in *udp_in)
{
	struct mbuf *opts = NULL;
	int ret;

	KASSERT(INP_ISIPV4(last), ("not inet inpcb"));

	if (last->inp_flags & INP_CONTROLOPTS ||
	    last->inp_socket->so_options & SO_TIMESTAMP)
		ip_savecontrol(last, &opts, ip, n);
	m_adj(n, off);

	lwkt_gettoken(&last->inp_socket->so_rcv.ssb_token);
	ret = ssb_appendaddr(&last->inp_socket->so_rcv,
	    (struct sockaddr *)udp_in, n, opts);
	lwkt_reltoken(&last->inp_socket->so_rcv.ssb_token);
	if (ret == 0) {
		m_freem(n);
		if (opts)
			m_freem(opts);
		udp_stat.udps_fullsock++;
	} else {
		sorwakeup(last->inp_socket);
	}
}
コード例 #8
0
/*
 * socantrcvmore(): indicates that no more data will be received and
 * will normally be applied to the socket by a protocol when it detects
 * that the peer will send no more data.  Data queued for reading in
 * the socket may yet be read.
 */
void
socantrcvmore(struct socket *so)
{
	KASSERT(solocked(so));

	so->so_state |= SS_CANTRCVMORE;
	sorwakeup(so);
}
コード例 #9
0
ファイル: uipc_socket2.c プロジェクト: ajinkya93/OpenBSD
void
soisconnected(struct socket *so)
{
	struct socket *head = so->so_head;

	so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING);
	so->so_state |= SS_ISCONNECTED;
	if (head && soqremque(so, 0)) {
		soqinsque(head, so, 1);
		sorwakeup(head);
		wakeup_one(&head->so_timeo);
	} else {
		wakeup(&so->so_timeo);
		sorwakeup(so);
		sowwakeup(so);
	}
}
コード例 #10
0
ファイル: uipc_socket2.c プロジェクト: ajinkya93/OpenBSD
/*
 * When an attempt at a new connection is noted on a socket
 * which accepts connections, sonewconn is called.  If the
 * connection is possible (subject to space constraints, etc.)
 * then we allocate a new structure, properly linked into the
 * data structure of the original socket, and return this.
 * Connstatus may be 0 or SS_ISCONNECTED.
 *
 * Must be called at splsoftnet()
 */
struct socket *
sonewconn(struct socket *head, int connstatus)
{
	struct socket *so;
	int soqueue = connstatus ? 1 : 0;

	splsoftassert(IPL_SOFTNET);

	if (mclpools[0].pr_nout > mclpools[0].pr_hardlimit * 95 / 100)
		return (NULL);
	if (head->so_qlen + head->so_q0len > head->so_qlimit * 3)
		return (NULL);
	so = pool_get(&socket_pool, PR_NOWAIT|PR_ZERO);
	if (so == NULL)
		return (NULL);
	so->so_type = head->so_type;
	so->so_options = head->so_options &~ SO_ACCEPTCONN;
	so->so_linger = head->so_linger;
	so->so_state = head->so_state | SS_NOFDREF;
	so->so_proto = head->so_proto;
	so->so_timeo = head->so_timeo;
	so->so_pgid = head->so_pgid;
	so->so_euid = head->so_euid;
	so->so_ruid = head->so_ruid;
	so->so_egid = head->so_egid;
	so->so_rgid = head->so_rgid;
	so->so_cpid = head->so_cpid;
	so->so_siguid = head->so_siguid;
	so->so_sigeuid = head->so_sigeuid;

	/*
	 * Inherit watermarks but those may get clamped in low mem situations.
	 */
	if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat)) {
		pool_put(&socket_pool, so);
		return (NULL);
	}
	so->so_snd.sb_wat = head->so_snd.sb_wat;
	so->so_snd.sb_lowat = head->so_snd.sb_lowat;
	so->so_snd.sb_timeo = head->so_snd.sb_timeo;
	so->so_rcv.sb_wat = head->so_rcv.sb_wat;
	so->so_rcv.sb_lowat = head->so_rcv.sb_lowat;
	so->so_rcv.sb_timeo = head->so_rcv.sb_timeo;

	soqinsque(head, so, soqueue);
	if ((*so->so_proto->pr_usrreq)(so, PRU_ATTACH, NULL, NULL, NULL,
	    curproc)) {
		(void) soqremque(so, soqueue);
		pool_put(&socket_pool, so);
		return (NULL);
	}
	if (connstatus) {
		sorwakeup(head);
		wakeup(&head->so_timeo);
		so->so_state |= connstatus;
	}
	return (so);
}
コード例 #11
0
ファイル: uipc_socket2.c プロジェクト: 0871087123/rtems
void
soisdisconnected(struct socket *so)
{

	so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
	so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE);
	soconnwakeup(so);
	sowwakeup(so);
	sorwakeup(so);
}
コード例 #12
0
ファイル: uipc_socket2.c プロジェクト: ajinkya93/OpenBSD
void
soisdisconnecting(struct socket *so)
{

	so->so_state &= ~SS_ISCONNECTING;
	so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
	wakeup(&so->so_timeo);
	sowwakeup(so);
	sorwakeup(so);
}
コード例 #13
0
/*
 * natmintr: interrupt
 *
 * Note: we expect a socket pointer in rcvif rather than an interface
 * pointer.  We can get the interface pointer from the so's PCB if we really
 * need it.
 */
void
natmintr(struct mbuf *m)
{
	struct socket *so;
	struct natmpcb *npcb;

#ifdef DIAGNOSTIC
	M_ASSERTPKTHDR(m);
#endif

	NATM_LOCK();
	npcb = (struct natmpcb *)m->m_pkthdr.rcvif;	/* XXX: overloaded */
	so = npcb->npcb_socket;

	npcb->npcb_inq--;

	if (npcb->npcb_flags & NPCB_DRAIN) {
		if (npcb->npcb_inq == 0)
			free(npcb, M_PCB);			/* done! */
		NATM_UNLOCK();
		m_freem(m);
		return;
	}

	if (npcb->npcb_flags & NPCB_FREE) {
		NATM_UNLOCK();
		m_freem(m);					/* drop */
		return;
	}

#ifdef NEED_TO_RESTORE_IFP
	m->m_pkthdr.rcvif = npcb->npcb_ifp;
#else
#ifdef DIAGNOSTIC
	m->m_pkthdr.rcvif = NULL;	/* null it out to be safe */
#endif
#endif

	if (sbspace(&so->so_rcv) > m->m_pkthdr.len) {
#ifdef NATM_STAT
		natm_sookcnt++;
		natm_sookbytes += m->m_pkthdr.len;
#endif
		sbappendrecord(&so->so_rcv, m);
		sorwakeup(so);
		NATM_UNLOCK();
	} else {
#ifdef NATM_STAT
		natm_sodropcnt++;
		natm_sodropbytes += m->m_pkthdr.len;
#endif
		NATM_UNLOCK();
		m_freem(m);
	}
}
コード例 #14
0
ファイル: uipc_socket2.c プロジェクト: 0871087123/rtems
void
soisconnected(struct socket *so)
{
	register struct socket *head = so->so_head;

	so->so_state &= ~(SS_ISCONNECTING|SS_ISDISCONNECTING|SS_ISCONFIRMING);
	so->so_state |= SS_ISCONNECTED;
	if (head && (so->so_state & SS_INCOMP)) {
		TAILQ_REMOVE(&head->so_incomp, so, so_list);
		head->so_incqlen--;
		so->so_state &= ~SS_INCOMP;
		TAILQ_INSERT_TAIL(&head->so_comp, so, so_list);
		so->so_state |= SS_COMP;
		sorwakeup(head);
		soconnwakeup(head);
	} else {
		soconnwakeup(so);
		sorwakeup(so);
		sowwakeup(so);
	}
}
コード例 #15
0
void
soisdisconnected(struct socket *so)
{

	KASSERT(solocked(so));

	so->so_state &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_ISDISCONNECTING);
	so->so_state |= (SS_CANTRCVMORE|SS_CANTSENDMORE|SS_ISDISCONNECTED);
	cv_broadcast(&so->so_cv);
	sowwakeup(so);
	sorwakeup(so);
}
コード例 #16
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;
}
コード例 #17
0
void
soisdisconnecting(struct socket *so)
{

	KASSERT(solocked(so));

	so->so_state &= ~SS_ISCONNECTING;
	so->so_state |= (SS_ISDISCONNECTING|SS_CANTRCVMORE|SS_CANTSENDMORE);
#if 0
	cv_broadcast(&so->so_cv);
#endif
	sowwakeup(so);
	sorwakeup(so);
}
コード例 #18
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);
}
コード例 #19
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);
}
コード例 #20
0
ファイル: socket.c プロジェクト: ECE492W2014G4/G4Capstone
/* FUNCTION: sorflush()
 * 
 * PARAM1: struct socket *    socket structure
 *
 * RETURNS: none
 *
 * Closes the "read" half of the socket connection. No more data
 * can be received on the socket, and any data currently in the 
 * socket receive buffer is discarded. Wakeup any processes waiting
 * on the socket.
 */
void
sorflush(struct socket * so)
{
   struct sockbuf *sb =  &so->so_rcv;
   int   s;

   sblock(sb);
   socantrcvmore(so);
   sbunlock(sb);
   sbrelease(sb);
   MEMSET((char *)sb, 0, sizeof (*sb));
   s = so->so_error;
   so->so_error = ESHUTDOWN;
   sorwakeup(so);
   so->so_error = s;
}
コード例 #21
0
ファイル: udp_usrreq.c プロジェクト: ChristosKa/freebsd
/*
 * Notify a udp user of an asynchronous error; just wake up so that they can
 * collect error status.
 */
struct inpcb *
udp_notify(struct inpcb *inp, int errno)
{

	/*
	 * While udp_ctlinput() always calls udp_notify() with a read lock
	 * when invoking it directly, in_pcbnotifyall() currently uses write
	 * locks due to sharing code with TCP.  For now, accept either a read
	 * or a write lock, but a read lock is sufficient.
	 */
	INP_LOCK_ASSERT(inp);

	inp->inp_socket->so_error = errno;
	sorwakeup(inp->inp_socket);
	sowwakeup(inp->inp_socket);
	return (inp);
}
コード例 #22
0
static void
sco_input(void *arg, struct mbuf *m)
{
	struct socket *so = arg;

	/*
	 * since this data is time sensitive, if the buffer
	 * is full we just dump data until the latest one
	 * will fit.
	 */

	while (m->m_pkthdr.len > sbspace(&so->so_rcv))
		sbdroprecord(&so->so_rcv);

	DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len);

	sbappendrecord(&so->so_rcv, m);
	sorwakeup(so);
}
コード例 #23
0
ファイル: keysock.c プロジェクト: MarginC/kame
key_receive(struct socket *so, struct mbuf **paddr, struct uio *uio,
	struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
#endif
{
	struct rawcb *rp = sotorawcb(so);
	struct keycb *kp = (struct keycb *)rp;
	int error;

#ifndef __FreeBSD__
	error = (*kp->kp_receive)(so, paddr, uio, mp0, controlp, flagsp);
#else
	error = soreceive(so, paddr, uio, mp0, controlp, flagsp);
#endif
	if (kp->kp_queue &&
	    sbspace(&rp->rcb_socket->so_rcv) > kp->kp_queue->m_pkthdr.len)
		sorwakeup(so);

	return error;
}
コード例 #24
0
static int
soo_drain(struct fileproc *fp, __unused vfs_context_t ctx)
{
    int error = 0;
    struct socket *so = (struct socket *)fp->f_fglob->fg_data;

    if (so) {
        socket_lock(so, 1);
        so->so_state |= SS_DRAINING;

        wakeup((caddr_t)&so->so_timeo);
        sorwakeup(so);
        sowwakeup(so);

        socket_unlock(so, 1);
    }

    return (error);
}
コード例 #25
0
ファイル: userfw_domain.c プロジェクト: gelraen/userfw
int
userfw_domain_send_to_socket(struct socket *so, unsigned char *buf, size_t len)
{
	struct mbchain m;
	int err;

	mb_init(&m);
	err = mb_put_mem(&m, buf, len, MB_MSYSTEM);
	if (err != 0)
	{
		mb_done(&m);
		return err;
	}

	sbappendstream(&(so->so_rcv), mb_detach(&m));
	sorwakeup(so);

	return 0;
}
コード例 #26
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);
}
コード例 #27
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);
}
コード例 #28
0
/*
 * When an attempt at a new connection is noted on a socket
 * which accepts connections, sonewconn is called.  If the
 * connection is possible (subject to space constraints, etc.)
 * then we allocate a new structure, propoerly linked into the
 * data structure of the original socket, and return this.
 * Connstatus may be 0, SS_ISCONFIRMING, or SS_ISCONNECTED.
 */
struct socket *
sonewconn(struct socket *head, int connstatus)
{
	struct socket	*so;
	int		soqueue, error;

	KASSERT(connstatus == 0 || connstatus == SS_ISCONFIRMING ||
	    connstatus == SS_ISCONNECTED);
	KASSERT(solocked(head));

	if ((head->so_options & SO_ACCEPTFILTER) != 0)
		connstatus = 0;
	soqueue = connstatus ? 1 : 0;
	if (head->so_qlen + head->so_q0len > 3 * head->so_qlimit / 2)
		return NULL;
	so = soget(false);
	if (so == NULL)
		return NULL;
	mutex_obj_hold(head->so_lock);
//	so->so_lock = head->so_lock;
	so->so_type = head->so_type;
	so->so_options = head->so_options &~ SO_ACCEPTCONN;
	so->so_linger = head->so_linger;
	so->so_state = head->so_state | SS_NOFDREF;
	so->so_proto = head->so_proto;
	so->so_timeo = head->so_timeo;
#if 0 /* VADIM */
	so->so_pgid = head->so_pgid;
	so->so_send = head->so_send;
	so->so_receive = head->so_receive;
	so->so_uidinfo = head->so_uidinfo;
	so->so_cpid = head->so_cpid;
#else
	so->glueing_block = NULL;
#endif
#ifdef MBUFTRACE
	so->so_mowner = head->so_mowner;
	so->so_rcv.sb_mowner = head->so_rcv.sb_mowner;
	so->so_snd.sb_mowner = head->so_snd.sb_mowner;
#endif
	if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) != 0)
		goto out;
	so->so_snd.sb_lowat = head->so_snd.sb_lowat;
	so->so_rcv.sb_lowat = head->so_rcv.sb_lowat;
	so->so_rcv.sb_timeo = head->so_rcv.sb_timeo;
	so->so_snd.sb_timeo = head->so_snd.sb_timeo;
	so->so_rcv.sb_flags |= head->so_rcv.sb_flags & (SB_AUTOSIZE | SB_ASYNC);
	so->so_snd.sb_flags |= head->so_snd.sb_flags & (SB_AUTOSIZE | SB_ASYNC);
	soqinsque(head, so, soqueue);
	error = (*so->so_proto->pr_usrreq)(so, PRU_ATTACH, NULL, NULL,
	    NULL);
	KASSERT(solocked(so));
	if (error != 0) {
		(void) soqremque(so, soqueue);
out:
		/*
		 * Remove acccept filter if one is present.
		 * XXX Is this really needed?
		 */
#if 0 /*VADIM*/
		if (so->so_accf != NULL)
			(void)accept_filt_clear(so);
#endif
		soput(so);
		return NULL;
	}
	if (connstatus) {
		sorwakeup(head);
#if 0
		cv_broadcast(&head->so_cv);
#endif
		so->so_state |= connstatus;
	}
	return so;
}
コード例 #29
0
ファイル: udp_usrreq.c プロジェクト: iHaD/DragonFlyBSD
int
udp_input(struct mbuf **mp, int *offp, int proto)
{
	struct sockaddr_in udp_in = { sizeof udp_in, AF_INET };
	int iphlen;
	struct ip *ip;
	struct udphdr *uh;
	struct inpcb *inp;
	struct mbuf *m;
	struct mbuf *opts = NULL;
	int len, off;
	struct ip save_ip;
	struct inpcbinfo *pcbinfo = &udbinfo[mycpuid];

	off = *offp;
	m = *mp;
	*mp = NULL;

	iphlen = off;
	udp_stat.udps_ipackets++;

	/*
	 * Strip IP options, if any; should skip this,
	 * make available to user, and use on returned packets,
	 * but we don't yet have a way to check the checksum
	 * with options still present.
	 */
	if (iphlen > sizeof(struct ip)) {
		ip_stripoptions(m);
		iphlen = sizeof(struct ip);
	}

	/*
	 * IP and UDP headers are together in first mbuf.
	 * Already checked and pulled up in ip_demux().
	 */
	KASSERT(m->m_len >= iphlen + sizeof(struct udphdr),
	    ("UDP header not in one mbuf"));

	ip = mtod(m, struct ip *);
	uh = (struct udphdr *)((caddr_t)ip + iphlen);

	/* destination port of 0 is illegal, based on RFC768. */
	if (uh->uh_dport == 0)
		goto bad;

	/*
	 * Make mbuf data length reflect UDP length.
	 * If not enough data to reflect UDP length, drop.
	 */
	len = ntohs((u_short)uh->uh_ulen);
	if (ip->ip_len != len) {
		if (len > ip->ip_len || len < sizeof(struct udphdr)) {
			udp_stat.udps_badlen++;
			goto bad;
		}
		m_adj(m, len - ip->ip_len);
		/* ip->ip_len = len; */
	}
	/*
	 * Save a copy of the IP header in case we want restore it
	 * for sending an ICMP error message in response.
	 */
	save_ip = *ip;

	/*
	 * Checksum extended UDP header and data.
	 */
	if (uh->uh_sum) {
		if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
			if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
				uh->uh_sum = m->m_pkthdr.csum_data;
			else
				uh->uh_sum = in_pseudo(ip->ip_src.s_addr,
				    ip->ip_dst.s_addr, htonl((u_short)len +
				    m->m_pkthdr.csum_data + IPPROTO_UDP));
			uh->uh_sum ^= 0xffff;
		} else {
			char b[9];

			bcopy(((struct ipovly *)ip)->ih_x1, b, 9);
			bzero(((struct ipovly *)ip)->ih_x1, 9);
			((struct ipovly *)ip)->ih_len = uh->uh_ulen;
			uh->uh_sum = in_cksum(m, len + sizeof(struct ip));
			bcopy(b, ((struct ipovly *)ip)->ih_x1, 9);
		}
		if (uh->uh_sum) {
			udp_stat.udps_badsum++;
			m_freem(m);
			return(IPPROTO_DONE);
		}
	} else
		udp_stat.udps_nosum++;

	if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
	    in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
	    	struct inpcbhead *connhead;
		struct inpcontainer *ic, *ic_marker;
		struct inpcontainerhead *ichead;
		struct udp_mcast_arg arg;
		struct inpcb *last;
		int error;

		/*
		 * Deliver a multicast or broadcast datagram to *all* sockets
		 * for which the local and remote addresses and ports match
		 * those of the incoming datagram.  This allows more than
		 * one process to receive multi/broadcasts on the same port.
		 * (This really ought to be done for unicast datagrams as
		 * well, but that would cause problems with existing
		 * applications that open both address-specific sockets and
		 * a wildcard socket listening to the same port -- they would
		 * end up receiving duplicates of every unicast datagram.
		 * Those applications open the multiple sockets to overcome an
		 * inadequacy of the UDP socket interface, but for backwards
		 * compatibility we avoid the problem here rather than
		 * fixing the interface.  Maybe 4.5BSD will remedy this?)
		 */

		/*
		 * Construct sockaddr format source address.
		 */
		udp_in.sin_port = uh->uh_sport;
		udp_in.sin_addr = ip->ip_src;
		arg.udp_in = &udp_in;
		/*
		 * Locate pcb(s) for datagram.
		 * (Algorithm copied from raw_intr().)
		 */
		last = NULL;
		arg.iphlen = iphlen;

		connhead = &pcbinfo->hashbase[
		    INP_PCBCONNHASH(ip->ip_src.s_addr, uh->uh_sport,
		    ip->ip_dst.s_addr, uh->uh_dport, pcbinfo->hashmask)];
		LIST_FOREACH(inp, connhead, inp_hash) {
#ifdef INET6
			if (!INP_ISIPV4(inp))
				continue;
#endif
			if (!in_hosteq(inp->inp_faddr, ip->ip_src) ||
			    !in_hosteq(inp->inp_laddr, ip->ip_dst) ||
			    inp->inp_fport != uh->uh_sport ||
			    inp->inp_lport != uh->uh_dport)
				continue;

			arg.inp = inp;
			arg.last = last;
			arg.ip = ip;
			arg.m = m;

			error = udp_mcast_input(&arg);
			if (error == ERESTART)
				continue;
			last = arg.last;

			if (error == EJUSTRETURN)
				goto done;
		}

		ichead = &pcbinfo->wildcardhashbase[
		    INP_PCBWILDCARDHASH(uh->uh_dport,
		    pcbinfo->wildcardhashmask)];
		ic_marker = in_pcbcontainer_marker(mycpuid);

		GET_PCBINFO_TOKEN(pcbinfo);
		LIST_INSERT_HEAD(ichead, ic_marker, ic_list);
		while ((ic = LIST_NEXT(ic_marker, ic_list)) != NULL) {
			LIST_REMOVE(ic_marker, ic_list);
			LIST_INSERT_AFTER(ic, ic_marker, ic_list);

			inp = ic->ic_inp;
			if (inp->inp_flags & INP_PLACEMARKER)
				continue;
#ifdef INET6
			if (!INP_ISIPV4(inp))
				continue;
#endif
			if (inp->inp_lport != uh->uh_dport)
				continue;
			if (inp->inp_laddr.s_addr != INADDR_ANY &&
			    inp->inp_laddr.s_addr != ip->ip_dst.s_addr)
				continue;

			arg.inp = inp;
			arg.last = last;
			arg.ip = ip;
			arg.m = m;

			error = udp_mcast_input(&arg);
			if (error == ERESTART)
				continue;
			last = arg.last;

			if (error == EJUSTRETURN)
				break;
		}
		LIST_REMOVE(ic_marker, ic_list);
		REL_PCBINFO_TOKEN(pcbinfo);
done:
		if (last == NULL) {
			/*
			 * No matching pcb found; discard datagram.
			 * (No need to send an ICMP Port Unreachable
			 * for a broadcast or multicast datgram.)
			 */
			udp_stat.udps_noportbcast++;
			goto bad;
		}
#ifdef IPSEC
		/* check AH/ESP integrity. */
		if (ipsec4_in_reject_so(m, last->inp_socket)) {
			ipsecstat.in_polvio++;
			goto bad;
		}
#endif /*IPSEC*/
#ifdef FAST_IPSEC
		/* check AH/ESP integrity. */
		if (ipsec4_in_reject(m, last))
			goto bad;
#endif /*FAST_IPSEC*/
		udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
		    &udp_in);
		return(IPPROTO_DONE);
	}
	/*
	 * Locate pcb for datagram.
	 */
	inp = in_pcblookup_pkthash(pcbinfo, ip->ip_src, uh->uh_sport,
	    ip->ip_dst, uh->uh_dport, TRUE, m->m_pkthdr.rcvif,
	    udp_reuseport_ext ? m : NULL);
	if (inp == NULL) {
		if (log_in_vain) {
			char buf[sizeof "aaa.bbb.ccc.ddd"];

			strcpy(buf, inet_ntoa(ip->ip_dst));
			log(LOG_INFO,
			    "Connection attempt to UDP %s:%d from %s:%d\n",
			    buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
			    ntohs(uh->uh_sport));
		}
		udp_stat.udps_noport++;
		if (m->m_flags & (M_BCAST | M_MCAST)) {
			udp_stat.udps_noportbcast++;
			goto bad;
		}
		if (blackhole)
			goto bad;
#ifdef ICMP_BANDLIM
		if (badport_bandlim(BANDLIM_ICMP_UNREACH) < 0)
			goto bad;
#endif
		*ip = save_ip;
		ip->ip_len += iphlen;
		icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
		return(IPPROTO_DONE);
	}
	KASSERT(INP_ISIPV4(inp), ("not inet inpcb"));
#ifdef IPSEC
	if (ipsec4_in_reject_so(m, inp->inp_socket)) {
		ipsecstat.in_polvio++;
		goto bad;
	}
#endif /*IPSEC*/
#ifdef FAST_IPSEC
	if (ipsec4_in_reject(m, inp))
		goto bad;
#endif /*FAST_IPSEC*/
	/*
	 * Check the minimum TTL for socket.
	 */
	if (ip->ip_ttl < inp->inp_ip_minttl)
		goto bad;

	/*
	 * Construct sockaddr format source address.
	 * Stuff source address and datagram in user buffer.
	 */
	udp_in.sin_port = uh->uh_sport;
	udp_in.sin_addr = ip->ip_src;
	if ((inp->inp_flags & INP_CONTROLOPTS) ||
	    (inp->inp_socket->so_options & SO_TIMESTAMP))
		ip_savecontrol(inp, &opts, ip, m);
	m_adj(m, iphlen + sizeof(struct udphdr));

	lwkt_gettoken(&inp->inp_socket->so_rcv.ssb_token);
	if (ssb_appendaddr(&inp->inp_socket->so_rcv,
	    (struct sockaddr *)&udp_in, m, opts) == 0) {
		lwkt_reltoken(&inp->inp_socket->so_rcv.ssb_token);
		udp_stat.udps_fullsock++;
		goto bad;
	}
	lwkt_reltoken(&inp->inp_socket->so_rcv.ssb_token);
	sorwakeup(inp->inp_socket);
	return(IPPROTO_DONE);
bad:
	m_freem(m);
	if (opts)
		m_freem(opts);
	return(IPPROTO_DONE);
}
コード例 #30
0
ファイル: natm.c プロジェクト: sofuture/bitrig
void
natmintr()

{
  int s;
  struct mbuf *m;
  struct socket *so;
  struct natmpcb *npcb;

next:
  s = splnet();
  IF_DEQUEUE(&natmintrq, m);
  splx(s);
  if (m == NULL)
    return;

#ifdef DIAGNOSTIC
  if ((m->m_flags & M_PKTHDR) == 0)
    panic("natmintr no HDR");
#endif

  npcb = (struct natmpcb *) m->m_pkthdr.rcvif; /* XXX: overloaded */
  so = npcb->npcb_socket;

  s = splnet();			/* could have atm devs @ different levels */
  npcb->npcb_inq--;
  splx(s);

  if (npcb->npcb_flags & NPCB_DRAIN) {
    m_freem(m);
    if (npcb->npcb_inq == 0)
      free(npcb, M_PCB);			/* done! */
    goto next;
  }

  if (npcb->npcb_flags & NPCB_FREE) {
    m_freem(m);					/* drop */
    goto next;
  }

#ifdef NEED_TO_RESTORE_IFP
  m->m_pkthdr.rcvif = npcb->npcb_ifp;
#else
#ifdef DIAGNOSTIC
m->m_pkthdr.rcvif = NULL;	/* null it out to be safe */
#endif
#endif

  if (sbspace(&so->so_rcv) > m->m_pkthdr.len ||
     ((npcb->npcb_flags & NPCB_RAW) != 0 && so->so_rcv.sb_cc < NPCB_RAWCC) ) {
#ifdef NATM_STAT
    natm_sookcnt++;
    natm_sookbytes += m->m_pkthdr.len;
#endif
    sbappendrecord(&so->so_rcv, m);
    sorwakeup(so);
  } else {
#ifdef NATM_STAT
    natm_sodropcnt++;
    natm_sodropbytes += m->m_pkthdr.len;
#endif
    m_freem(m);
  }

  goto next;
}