raw_ip.c

来自「eCos操作系统源码」· C语言 代码 · 共 695 行 · 第 1/2 页

C
695
字号
		case IP_FW_FLUSH:		case IP_FW_ZERO:		case IP_FW_RESETLOG:			if (ip_fw_ctl_ptr == 0)				error = ENOPROTOOPT;			else				error = ip_fw_ctl_ptr(sopt);			break;#ifdef DUMMYNET		case IP_DUMMYNET_CONFIGURE:		case IP_DUMMYNET_DEL:		case IP_DUMMYNET_FLUSH:			if (ip_dn_ctl_ptr == NULL)				error = ENOPROTOOPT ;			else				error = ip_dn_ctl_ptr(sopt);			break ;#endif		case IP_RSVP_ON:			error = ip_rsvp_init(so);			break;		case IP_RSVP_OFF:			error = ip_rsvp_done();			break;			/* XXX - should be combined */		case IP_RSVP_VIF_ON:			error = ip_rsvp_vif_init(so, sopt);			break;					case IP_RSVP_VIF_OFF:			error = ip_rsvp_vif_done(so, sopt);			break;		case MRT_INIT:		case MRT_DONE:		case MRT_ADD_VIF:		case MRT_DEL_VIF:		case MRT_ADD_MFC:		case MRT_DEL_MFC:		case MRT_VERSION:		case MRT_ASSERT:			error = ip_mrouter_set(so, sopt);			break;		default:			error = ip_ctloutput(so, sopt);			break;		}		break;	}	return (error);}/* * This function exists solely to receive the PRC_IFDOWN messages which * are sent by if_down().  It looks for an ifaddr whose ifa_addr is sa, * and calls in_ifadown() to remove all routes corresponding to that address. * It also receives the PRC_IFUP messages from if_up() and reinstalls the * interface routes. */voidrip_ctlinput(cmd, sa, vip)	int cmd;	struct sockaddr *sa;	void *vip;{	struct in_ifaddr *ia;	struct ifnet *ifp;	int err;	int flags;	switch (cmd) {	case PRC_IFDOWN:		for (ia = in_ifaddrhead.tqh_first; ia;		     ia = ia->ia_link.tqe_next) {			if (ia->ia_ifa.ifa_addr == sa			    && (ia->ia_flags & IFA_ROUTE)) {				/*				 * in_ifscrub kills the interface route.				 */				in_ifscrub(ia->ia_ifp, ia);				/*				 * in_ifadown gets rid of all the rest of				 * the routes.  This is not quite the right				 * thing to do, but at least if we are running				 * a routing process they will come back.				 */				in_ifadown(&ia->ia_ifa, 0);				break;			}		}		break;	case PRC_IFUP:		for (ia = in_ifaddrhead.tqh_first; ia;		     ia = ia->ia_link.tqe_next) {			if (ia->ia_ifa.ifa_addr == sa)				break;		}		if (ia == 0 || (ia->ia_flags & IFA_ROUTE))			return;		flags = RTF_UP;		ifp = ia->ia_ifa.ifa_ifp;		if ((ifp->if_flags & IFF_LOOPBACK)		    || (ifp->if_flags & IFF_POINTOPOINT))			flags |= RTF_HOST;		err = rtinit(&ia->ia_ifa, RTM_ADD, flags);		if (err == 0)			ia->ia_flags |= IFA_ROUTE;		break;	}}u_long	rip_sendspace = RIPSNDQ;u_long	rip_recvspace = RIPRCVQ;SYSCTL_INT(_net_inet_raw, OID_AUTO, maxdgram, CTLFLAG_RW,    &rip_sendspace, 0, "Maximum outgoing raw IP datagram size");SYSCTL_INT(_net_inet_raw, OID_AUTO, recvspace, CTLFLAG_RW,    &rip_recvspace, 0, "Maximum incoming raw IP datagram size");static intrip_attach(struct socket *so, int proto, struct proc *p){	struct inpcb *inp;	int error, s;	inp = sotoinpcb(so);	if (inp)		panic("rip_attach");	error = soreserve(so, rip_sendspace, rip_recvspace);	if (error)		return error;	s = splnet();	error = in_pcballoc(so, &ripcbinfo, p);	splx(s);	if (error)		return error;	inp = (struct inpcb *)so->so_pcb;	inp->inp_vflag |= INP_IPV4;	inp->inp_ip_p = proto;	inp->inp_ip_ttl = ip_defttl;	return 0;}static intrip_detach(struct socket *so){	struct inpcb *inp;	inp = sotoinpcb(so);	if (inp == 0)		panic("rip_detach");	if (so == ip_mrouter)		ip_mrouter_done();	ip_rsvp_force_done(so);	if (so == ip_rsvpd)		ip_rsvp_done();	in_pcbdetach(inp);	return 0;}static intrip_abort(struct socket *so){	soisdisconnected(so);	return rip_detach(so);}static intrip_disconnect(struct socket *so){	if ((so->so_state & SS_ISCONNECTED) == 0)		return ENOTCONN;	return rip_abort(so);}static intrip_bind(struct socket *so, struct sockaddr *nam, struct proc *p){	struct inpcb *inp = sotoinpcb(so);	struct sockaddr_in *addr = (struct sockaddr_in *)nam;	if (nam->sa_len != sizeof(*addr))		return EINVAL;	if (TAILQ_EMPTY(&ifnet) || ((addr->sin_family != AF_INET) &&				    (addr->sin_family != AF_IMPLINK)) ||	    (addr->sin_addr.s_addr &&	     ifa_ifwithaddr((struct sockaddr *)addr) == 0))		return EADDRNOTAVAIL;	inp->inp_laddr = addr->sin_addr;	return 0;}static intrip_connect(struct socket *so, struct sockaddr *nam, struct proc *p){	struct inpcb *inp = sotoinpcb(so);	struct sockaddr_in *addr = (struct sockaddr_in *)nam;	if (nam->sa_len != sizeof(*addr))		return EINVAL;	if (TAILQ_EMPTY(&ifnet))		return EADDRNOTAVAIL;	if ((addr->sin_family != AF_INET) &&	    (addr->sin_family != AF_IMPLINK))		return EAFNOSUPPORT;	inp->inp_faddr = addr->sin_addr;	soisconnected(so);	return 0;}static intrip_shutdown(struct socket *so){	socantsendmore(so);	return 0;}static intrip_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam,	 struct mbuf *control, struct proc *p){	struct inpcb *inp = sotoinpcb(so);	register u_long dst;	if (so->so_state & SS_ISCONNECTED) {		if (nam) {			m_freem(m);			return EISCONN;		}		dst = inp->inp_faddr.s_addr;	} else {		if (nam == NULL) {			m_freem(m);			return ENOTCONN;		}		dst = ((struct sockaddr_in *)nam)->sin_addr.s_addr;	}	return rip_output(m, so, dst);}#ifdef CYGPKG_NET_FREEBSD_SYSCTLstatic intrip_pcblist(SYSCTL_HANDLER_ARGS){	int error, i, n, s;	struct inpcb *inp, **inp_list;	inp_gen_t gencnt;	struct xinpgen xig;	/*	 * The process of preparing the TCB list is too time-consuming and	 * resource-intensive to repeat twice on every request.	 */	if (req->oldptr == 0) {		n = ripcbinfo.ipi_count;		req->oldidx = 2 * (sizeof xig)			+ (n + n/8) * sizeof(struct xinpcb);		return 0;	}	if (req->newptr != 0)		return EPERM;	/*	 * OK, now we're committed to doing something.	 */	s = splnet();	gencnt = ripcbinfo.ipi_gencnt;	n = ripcbinfo.ipi_count;	splx(s);	xig.xig_len = sizeof xig;	xig.xig_count = n;	xig.xig_gen = gencnt;	xig.xig_sogen = so_gencnt;	error = SYSCTL_OUT(req, &xig, sizeof xig);	if (error)		return error;	inp_list = malloc(n * sizeof *inp_list, M_TEMP, M_WAITOK);	if (inp_list == 0)		return ENOMEM;		s = splnet();	for (inp = ripcbinfo.listhead->lh_first, i = 0; inp && i < n;	     inp = inp->inp_list.le_next) {		if (inp->inp_gencnt <= gencnt)			inp_list[i++] = inp;	}	splx(s);	n = i;	error = 0;	for (i = 0; i < n; i++) {		inp = inp_list[i];		if (inp->inp_gencnt <= gencnt) {			struct xinpcb xi;			xi.xi_len = sizeof xi;			/* XXX should avoid extra copy */			bcopy(inp, &xi.xi_inp, sizeof *inp);			if (inp->inp_socket)				sotoxsocket(inp->inp_socket, &xi.xi_socket);			error = SYSCTL_OUT(req, &xi, sizeof xi);		}	}	if (!error) {		/*		 * Give the user an updated idea of our state.		 * If the generation differs from what we told		 * her before, she knows that something happened		 * while we were processing this request, and it		 * might be necessary to retry.		 */		s = splnet();		xig.xig_gen = ripcbinfo.ipi_gencnt;		xig.xig_sogen = so_gencnt;		xig.xig_count = ripcbinfo.ipi_count;		splx(s);		error = SYSCTL_OUT(req, &xig, sizeof xig);	}	free(inp_list, M_TEMP);	return error;}#endifSYSCTL_PROC(_net_inet_raw, OID_AUTO/*XXX*/, pcblist, CTLFLAG_RD, 0, 0,	    rip_pcblist, "S,xinpcb", "List of active raw IP sockets");struct pr_usrreqs rip_usrreqs = {	rip_abort, pru_accept_notsupp, rip_attach, rip_bind, rip_connect,	pru_connect2_notsupp, in_control, rip_detach, rip_disconnect,	pru_listen_notsupp, in_setpeeraddr, pru_rcvd_notsupp,	pru_rcvoob_notsupp, rip_send, pru_sense_null, rip_shutdown,	in_setsockaddr, sosend, soreceive, sopoll};

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?