version 1.14, 1994/06/29 06:38:31 |
version 1.25.4.1, 1996/11/10 21:57:53 |
|
|
#include <netinet/ip_var.h> |
#include <netinet/ip_var.h> |
#include <netinet/ip_mroute.h> |
#include <netinet/ip_mroute.h> |
#include <netinet/in_pcb.h> |
#include <netinet/in_pcb.h> |
|
#include <netinet/in_var.h> |
|
|
struct inpcb rawinpcb; |
#include <machine/stdarg.h> |
|
|
|
struct inpcbtable rawcbtable; |
|
|
/* |
/* |
* Nominal space allocated to a raw ip socket. |
* Nominal space allocated to a raw ip socket. |
|
|
rip_init() |
rip_init() |
{ |
{ |
|
|
rawinpcb.inp_next = rawinpcb.inp_prev = &rawinpcb; |
in_pcbinit(&rawcbtable, 1); |
} |
} |
|
|
struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; |
struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; |
Line 83 struct sockaddr_in ripsrc = { sizeof(rip |
|
Line 86 struct sockaddr_in ripsrc = { sizeof(rip |
|
* mbuf chain. |
* mbuf chain. |
*/ |
*/ |
void |
void |
rip_input(m) |
#if __STDC__ |
|
rip_input(struct mbuf *m, ...) |
|
#else |
|
rip_input(m, va_alist) |
struct mbuf *m; |
struct mbuf *m; |
|
va_dcl |
|
#endif |
{ |
{ |
register struct ip *ip = mtod(m, struct ip *); |
register struct ip *ip = mtod(m, struct ip *); |
register struct inpcb *inp; |
register struct inpcb *inp; |
struct socket *last = 0; |
struct socket *last = 0; |
|
|
ripsrc.sin_addr = ip->ip_src; |
ripsrc.sin_addr = ip->ip_src; |
for (inp = rawinpcb.inp_next; inp != &rawinpcb; inp = inp->inp_next) { |
for (inp = rawcbtable.inpt_queue.cqh_first; |
|
inp != (struct inpcb *)&rawcbtable.inpt_queue; |
|
inp = inp->inp_queue.cqe_next) { |
if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) |
if (inp->inp_ip.ip_p && inp->inp_ip.ip_p != ip->ip_p) |
continue; |
continue; |
if (inp->inp_laddr.s_addr && |
if (inp->inp_laddr.s_addr && |
inp->inp_laddr.s_addr == ip->ip_dst.s_addr) |
inp->inp_laddr.s_addr != ip->ip_dst.s_addr) |
continue; |
continue; |
if (inp->inp_faddr.s_addr && |
if (inp->inp_faddr.s_addr && |
inp->inp_faddr.s_addr == ip->ip_src.s_addr) |
inp->inp_faddr.s_addr != ip->ip_src.s_addr) |
continue; |
continue; |
if (last) { |
if (last) { |
struct mbuf *n; |
struct mbuf *n; |
if (n = m_copy(m, 0, (int)M_COPYALL)) { |
if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) { |
if (sbappendaddr(&last->so_rcv, |
if (sbappendaddr(&last->so_rcv, |
(struct sockaddr *)&ripsrc, |
sintosa(&ripsrc), n, |
n, (struct mbuf *)0) == 0) |
(struct mbuf *)0) == 0) |
/* should notify about lost packet */ |
/* should notify about lost packet */ |
m_freem(n); |
m_freem(n); |
else |
else |
|
|
last = inp->inp_socket; |
last = inp->inp_socket; |
} |
} |
if (last) { |
if (last) { |
if (sbappendaddr(&last->so_rcv, (struct sockaddr *)&ripsrc, |
if (sbappendaddr(&last->so_rcv, sintosa(&ripsrc), m, |
m, (struct mbuf *)0) == 0) |
(struct mbuf *)0) == 0) |
m_freem(m); |
m_freem(m); |
else |
else |
sorwakeup(last); |
sorwakeup(last); |
|
|
* Tack on options user may have setup with control call. |
* Tack on options user may have setup with control call. |
*/ |
*/ |
int |
int |
rip_output(m, so, dst) |
#if __STDC__ |
register struct mbuf *m; |
rip_output(struct mbuf *m, ...) |
|
#else |
|
rip_output(m, va_alist) |
|
struct mbuf *m; |
|
va_dcl |
|
#endif |
|
{ |
struct socket *so; |
struct socket *so; |
u_long dst; |
u_long dst; |
{ |
|
register struct ip *ip; |
register struct ip *ip; |
register struct inpcb *inp = sotoinpcb(so); |
register struct inpcb *inp; |
struct mbuf *opts; |
struct mbuf *opts; |
int flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; |
int flags; |
|
va_list ap; |
|
|
|
va_start(ap, m); |
|
so = va_arg(ap, struct socket *); |
|
dst = va_arg(ap, u_long); |
|
va_end(ap); |
|
|
|
inp = sotoinpcb(so); |
|
flags = (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST; |
|
|
/* |
/* |
* If the user handed us a complete IP packet, use it. |
* If the user handed us a complete IP packet, use it. |
* Otherwise, allocate an mbuf for a header and fill it in. |
* Otherwise, allocate an mbuf for a header and fill it in. |
*/ |
*/ |
if ((inp->inp_flags & INP_HDRINCL) == 0) { |
if ((inp->inp_flags & INP_HDRINCL) == 0) { |
|
if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { |
|
m_freem(m); |
|
return (EMSGSIZE); |
|
} |
M_PREPEND(m, sizeof(struct ip), M_WAIT); |
M_PREPEND(m, sizeof(struct ip), M_WAIT); |
ip = mtod(m, struct ip *); |
ip = mtod(m, struct ip *); |
ip->ip_tos = 0; |
ip->ip_tos = 0; |
Line 158 rip_output(m, so, dst) |
|
Line 186 rip_output(m, so, dst) |
|
ip->ip_ttl = MAXTTL; |
ip->ip_ttl = MAXTTL; |
opts = inp->inp_options; |
opts = inp->inp_options; |
} else { |
} else { |
|
if (m->m_pkthdr.len > IP_MAXPACKET) { |
|
m_freem(m); |
|
return (EMSGSIZE); |
|
} |
ip = mtod(m, struct ip *); |
ip = mtod(m, struct ip *); |
if (ip->ip_id == 0) |
if (ip->ip_id == 0) |
ip->ip_id = htons(ip_id++); |
ip->ip_id = htons(ip_id++); |
Line 180 rip_ctloutput(op, so, level, optname, m) |
|
Line 212 rip_ctloutput(op, so, level, optname, m) |
|
struct mbuf **m; |
struct mbuf **m; |
{ |
{ |
register struct inpcb *inp = sotoinpcb(so); |
register struct inpcb *inp = sotoinpcb(so); |
register int error; |
#ifdef MROUTING |
|
int error; |
|
#endif |
|
|
if (level != IPPROTO_IP) |
if (level != IPPROTO_IP) { |
|
if (m != 0 && *m != 0) |
|
(void)m_free(*m); |
return (EINVAL); |
return (EINVAL); |
|
} |
|
|
switch (optname) { |
switch (optname) { |
|
|
Line 205 rip_ctloutput(op, so, level, optname, m) |
|
Line 242 rip_ctloutput(op, so, level, optname, m) |
|
} |
} |
break; |
break; |
|
|
case DVMRP_INIT: |
case MRT_INIT: |
case DVMRP_DONE: |
case MRT_DONE: |
case DVMRP_ADD_VIF: |
case MRT_ADD_VIF: |
case DVMRP_DEL_VIF: |
case MRT_DEL_VIF: |
case DVMRP_ADD_LGRP: |
case MRT_ADD_MFC: |
case DVMRP_DEL_LGRP: |
case MRT_DEL_MFC: |
case DVMRP_ADD_MRT: |
case MRT_VERSION: |
case DVMRP_DEL_MRT: |
case MRT_ASSERT: |
#ifdef MROUTING |
#ifdef MROUTING |
if (op == PRCO_SETOPT) { |
switch (op) { |
error = ip_mrouter_cmd(optname, so, *m); |
case PRCO_SETOPT: |
if (*m) |
error = ip_mrouter_set(optname, so, m); |
(void)m_free(*m); |
break; |
} else |
case PRCO_GETOPT: |
|
error = ip_mrouter_get(optname, so, m); |
|
break; |
|
default: |
error = EINVAL; |
error = EINVAL; |
|
break; |
|
} |
return (error); |
return (error); |
#else |
#else |
if (op == PRCO_SETOPT && *m) |
if (op == PRCO_SETOPT && *m) |
(void)m_free(*m); |
m_free(*m); |
return (EOPNOTSUPP); |
return (EOPNOTSUPP); |
#endif |
#endif |
} |
} |
Line 245 rip_usrreq(so, req, m, nam, control) |
|
Line 287 rip_usrreq(so, req, m, nam, control) |
|
#ifdef MROUTING |
#ifdef MROUTING |
extern struct socket *ip_mrouter; |
extern struct socket *ip_mrouter; |
#endif |
#endif |
|
if (req == PRU_CONTROL) |
|
return (in_control(so, (long)m, (caddr_t)nam, |
|
(struct ifnet *)control)); |
|
|
|
if (inp == NULL && req != PRU_ATTACH) { |
|
error = EINVAL; |
|
goto release; |
|
} |
|
|
switch (req) { |
switch (req) { |
|
|
case PRU_ATTACH: |
case PRU_ATTACH: |
Line 255 rip_usrreq(so, req, m, nam, control) |
|
Line 306 rip_usrreq(so, req, m, nam, control) |
|
break; |
break; |
} |
} |
if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || |
if ((error = soreserve(so, rip_sendspace, rip_recvspace)) || |
(error = in_pcballoc(so, &rawinpcb))) |
(error = in_pcballoc(so, &rawcbtable))) |
break; |
break; |
inp = (struct inpcb *)so->so_pcb; |
inp = (struct inpcb *)so->so_pcb; |
inp->inp_ip.ip_p = (int)nam; |
inp->inp_ip.ip_p = (long)nam; |
break; |
break; |
|
|
case PRU_DISCONNECT: |
case PRU_DISCONNECT: |
Line 288 rip_usrreq(so, req, m, nam, control) |
|
Line 339 rip_usrreq(so, req, m, nam, control) |
|
error = EINVAL; |
error = EINVAL; |
break; |
break; |
} |
} |
if ((ifnet == 0) || |
if ((ifnet.tqh_first == 0) || |
((addr->sin_family != AF_INET) && |
((addr->sin_family != AF_INET) && |
(addr->sin_family != AF_IMPLINK)) || |
(addr->sin_family != AF_IMPLINK)) || |
(addr->sin_addr.s_addr && |
(addr->sin_addr.s_addr && |
ifa_ifwithaddr((struct sockaddr *)addr) == 0)) { |
ifa_ifwithaddr(sintosa(addr)) == 0)) { |
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
break; |
break; |
} |
} |
Line 307 rip_usrreq(so, req, m, nam, control) |
|
Line 358 rip_usrreq(so, req, m, nam, control) |
|
error = EINVAL; |
error = EINVAL; |
break; |
break; |
} |
} |
if (ifnet == 0) { |
if (ifnet.tqh_first == 0) { |
error = EADDRNOTAVAIL; |
error = EADDRNOTAVAIL; |
break; |
break; |
} |
} |
Line 338 rip_usrreq(so, req, m, nam, control) |
|
Line 389 rip_usrreq(so, req, m, nam, control) |
|
*/ |
*/ |
case PRU_SEND: |
case PRU_SEND: |
{ |
{ |
register u_long dst; |
register u_int32_t dst; |
|
|
if (so->so_state & SS_ISCONNECTED) { |
if (so->so_state & SS_ISCONNECTED) { |
if (nam) { |
if (nam) { |
Line 386 rip_usrreq(so, req, m, nam, control) |
|
Line 437 rip_usrreq(so, req, m, nam, control) |
|
default: |
default: |
panic("rip_usrreq"); |
panic("rip_usrreq"); |
} |
} |
|
release: |
if (m != NULL) |
if (m != NULL) |
m_freem(m); |
m_freem(m); |
return (error); |
return (error); |