|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution is only permitted until one year after the first shipment ! 6: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 7: * binary forms are permitted provided that: (1) source distributions retain ! 8: * this entire copyright notice and comment, and (2) distributions including ! 9: * binaries display the following acknowledgement: This product includes ! 10: * software developed by the University of California, Berkeley and its ! 11: * contributors'' in the documentation or other materials provided with the ! 12: * distribution and in all advertising materials mentioning features or use ! 13: * of this software. Neither the name of the University nor the names of ! 14: * its contributors may be used to endorse or promote products derived from ! 15: * this software without specific prior written permission. ! 16: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 17: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 18: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 19: * ! 20: * @(#)raw_ip.c 7.8 (Berkeley) 7/25/90 ! 21: */ ! 22: ! 23: #include "param.h" ! 24: #include "malloc.h" ! 25: #include "mbuf.h" ! 26: #include "socket.h" ! 27: #include "protosw.h" ! 28: #include "socketvar.h" ! 29: #include "errno.h" ! 30: ! 31: #include "../net/if.h" ! 32: #include "../net/route.h" ! 33: #include "../net/raw_cb.h" ! 34: ! 35: #include "in.h" ! 36: #include "in_systm.h" ! 37: #include "ip.h" ! 38: #include "ip_var.h" ! 39: #include "in_pcb.h" ! 40: ! 41: /* ! 42: * Raw interface to IP protocol. ! 43: */ ! 44: ! 45: struct sockaddr_in ripdst = { sizeof(ripdst), AF_INET }; ! 46: struct sockaddr_in ripsrc = { sizeof(ripsrc), AF_INET }; ! 47: struct sockproto ripproto = { PF_INET }; ! 48: /* ! 49: * Setup generic address and protocol structures ! 50: * for raw_input routine, then pass them along with ! 51: * mbuf chain. ! 52: */ ! 53: rip_input(m) ! 54: struct mbuf *m; ! 55: { ! 56: register struct ip *ip = mtod(m, struct ip *); ! 57: ! 58: ripproto.sp_protocol = ip->ip_p; ! 59: ripdst.sin_addr = ip->ip_dst; ! 60: ripsrc.sin_addr = ip->ip_src; ! 61: if (raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, ! 62: (struct sockaddr *)&ripdst) == 0) { ! 63: ipstat.ips_noproto++; ! 64: ipstat.ips_delivered--; ! 65: } ! 66: } ! 67: ! 68: /* ! 69: * Generate IP header and pass packet to ip_output. ! 70: * Tack on options user may have setup with control call. ! 71: */ ! 72: #define satosin(sa) ((struct sockaddr_in *)(sa)) ! 73: rip_output(m, so) ! 74: register struct mbuf *m; ! 75: struct socket *so; ! 76: { ! 77: register struct ip *ip; ! 78: register struct raw_inpcb *rp = sotorawinpcb(so); ! 79: register struct sockaddr_in *sin; ! 80: ! 81: /* ! 82: * If the user handed us a complete IP packet, use it. ! 83: * Otherwise, allocate an mbuf for a header and fill it in. ! 84: */ ! 85: if (rp->rinp_flags & RINPF_HDRINCL) ! 86: ip = mtod(m, struct ip *); ! 87: else { ! 88: M_PREPEND(m, sizeof(struct ip), M_WAIT); ! 89: ip = mtod(m, struct ip *); ! 90: ip->ip_tos = 0; ! 91: ip->ip_off = 0; ! 92: ip->ip_p = rp->rinp_rcb.rcb_proto.sp_protocol; ! 93: ip->ip_len = m->m_pkthdr.len; ! 94: if (sin = satosin(rp->rinp_rcb.rcb_laddr)) { ! 95: ip->ip_src = sin->sin_addr; ! 96: } else ! 97: ip->ip_src.s_addr = 0; ! 98: if (sin = satosin(rp->rinp_rcb.rcb_faddr)) ! 99: ip->ip_dst = sin->sin_addr; ! 100: ip->ip_ttl = MAXTTL; ! 101: } ! 102: return (ip_output(m, ! 103: (rp->rinp_flags & RINPF_HDRINCL)? (struct mbuf *)0: rp->rinp_options, ! 104: &rp->rinp_route, ! 105: (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); ! 106: } ! 107: ! 108: /* ! 109: * Raw IP socket option processing. ! 110: */ ! 111: rip_ctloutput(op, so, level, optname, m) ! 112: int op; ! 113: struct socket *so; ! 114: int level, optname; ! 115: struct mbuf **m; ! 116: { ! 117: int error = 0; ! 118: register struct raw_inpcb *rp = sotorawinpcb(so); ! 119: ! 120: if (level != IPPROTO_IP) ! 121: error = EINVAL; ! 122: else switch (op) { ! 123: ! 124: case PRCO_SETOPT: ! 125: switch (optname) { ! 126: ! 127: case IP_OPTIONS: ! 128: return (ip_pcbopts(&rp->rinp_options, *m)); ! 129: ! 130: case IP_HDRINCL: ! 131: if (m == 0 || *m == 0 || (*m)->m_len < sizeof (int)) { ! 132: error = EINVAL; ! 133: break; ! 134: } ! 135: if (*mtod(*m, int *)) ! 136: rp->rinp_flags |= RINPF_HDRINCL; ! 137: else ! 138: rp->rinp_flags &= ~RINPF_HDRINCL; ! 139: break; ! 140: ! 141: default: ! 142: error = EINVAL; ! 143: break; ! 144: } ! 145: break; ! 146: ! 147: case PRCO_GETOPT: ! 148: *m = m_get(M_WAIT, MT_SOOPTS); ! 149: switch (optname) { ! 150: ! 151: case IP_OPTIONS: ! 152: if (rp->rinp_options) { ! 153: (*m)->m_len = rp->rinp_options->m_len; ! 154: bcopy(mtod(rp->rinp_options, caddr_t), ! 155: mtod(*m, caddr_t), (unsigned)(*m)->m_len); ! 156: } else ! 157: (*m)->m_len = 0; ! 158: break; ! 159: ! 160: case IP_HDRINCL: ! 161: (*m)->m_len = sizeof (int); ! 162: *mtod(*m, int *) = rp->rinp_flags & RINPF_HDRINCL; ! 163: break; ! 164: ! 165: default: ! 166: error = EINVAL; ! 167: m_freem(*m); ! 168: *m = 0; ! 169: break; ! 170: } ! 171: break; ! 172: } ! 173: if (op == PRCO_SETOPT && *m) ! 174: (void)m_free(*m); ! 175: return (error); ! 176: } ! 177: ! 178: /*ARGSUSED*/ ! 179: rip_usrreq(so, req, m, nam, rights, control) ! 180: register struct socket *so; ! 181: int req; ! 182: struct mbuf *m, *nam, *rights, *control; ! 183: { ! 184: register int error = 0; ! 185: register struct raw_inpcb *rp = sotorawinpcb(so); ! 186: ! 187: switch (req) { ! 188: ! 189: case PRU_ATTACH: ! 190: if (rp) ! 191: panic("rip_attach"); ! 192: MALLOC(rp, struct raw_inpcb *, sizeof *rp, M_PCB, M_WAITOK); ! 193: if (rp == 0) ! 194: return (ENOBUFS); ! 195: bzero((caddr_t)rp, sizeof *rp); ! 196: so->so_pcb = (caddr_t)rp; ! 197: break; ! 198: ! 199: case PRU_DETACH: ! 200: if (rp == 0) ! 201: panic("rip_detach"); ! 202: if (rp->rinp_options) ! 203: m_freem(rp->rinp_options); ! 204: if (rp->rinp_route.ro_rt) ! 205: RTFREE(rp->rinp_route.ro_rt); ! 206: if (rp->rinp_rcb.rcb_laddr) ! 207: rp->rinp_rcb.rcb_laddr = 0; ! 208: break; ! 209: ! 210: case PRU_BIND: ! 211: { ! 212: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); ! 213: ! 214: if (nam->m_len != sizeof(*addr)) ! 215: return (EINVAL); ! 216: if ((ifnet == 0) || ! 217: ((addr->sin_family != AF_INET) && ! 218: (addr->sin_family != AF_IMPLINK)) || ! 219: (addr->sin_addr.s_addr && ! 220: ifa_ifwithaddr((struct sockaddr *)addr) == 0)) ! 221: return (EADDRNOTAVAIL); ! 222: rp->rinp_rcb.rcb_laddr = (struct sockaddr *)&rp->rinp_laddr; ! 223: rp->rinp_laddr = *addr; ! 224: return (0); ! 225: } ! 226: case PRU_CONNECT: ! 227: { ! 228: struct sockaddr_in *addr = mtod(nam, struct sockaddr_in *); ! 229: ! 230: if (nam->m_len != sizeof(*addr)) ! 231: return (EINVAL); ! 232: if (ifnet == 0) ! 233: return (EADDRNOTAVAIL); ! 234: if ((addr->sin_family != AF_INET) && ! 235: (addr->sin_family != AF_IMPLINK)) ! 236: return (EAFNOSUPPORT); ! 237: rp->rinp_rcb.rcb_faddr = (struct sockaddr *)&rp->rinp_faddr; ! 238: rp->rinp_faddr = *addr; ! 239: soisconnected(so); ! 240: return (0); ! 241: } ! 242: } ! 243: error = raw_usrreq(so, req, m, nam, rights, control); ! 244: ! 245: if (error && (req == PRU_ATTACH) && so->so_pcb) ! 246: free(so->so_pcb, M_PCB); ! 247: return (error); ! 248: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.