123186Smckusick /* 223186Smckusick * Copyright (c) 1982 Regents of the University of California. 323186Smckusick * All rights reserved. The Berkeley software License Agreement 423186Smckusick * specifies the terms and conditions for redistribution. 523186Smckusick * 6*26037Skarels * @(#)raw_ip.c 6.7 (Berkeley) 02/02/86 723186Smckusick */ 85123Swnj 917062Sbloom #include "param.h" 1017062Sbloom #include "mbuf.h" 1117062Sbloom #include "socket.h" 1217062Sbloom #include "protosw.h" 1317062Sbloom #include "socketvar.h" 1417062Sbloom #include "errno.h" 1510894Ssam 166509Ssam #include "../net/if.h" 1713455Ssam #include "../net/route.h" 1810894Ssam #include "../net/raw_cb.h" 1910894Ssam 2017062Sbloom #include "in.h" 2117062Sbloom #include "in_systm.h" 2217062Sbloom #include "ip.h" 2317062Sbloom #include "ip_var.h" 245123Swnj 255123Swnj /* 265612Swnj * Raw interface to IP protocol. 275123Swnj */ 285612Swnj 2913455Ssam struct sockaddr_in ripdst = { AF_INET }; 3013455Ssam struct sockaddr_in ripsrc = { AF_INET }; 3113455Ssam struct sockproto ripproto = { PF_INET }; 325612Swnj /* 335612Swnj * Setup generic address and protocol structures 345612Swnj * for raw_input routine, then pass them along with 355612Swnj * mbuf chain. 365612Swnj */ 375123Swnj rip_input(m) 385123Swnj struct mbuf *m; 395123Swnj { 405612Swnj register struct ip *ip = mtod(m, struct ip *); 415123Swnj 425612Swnj ripproto.sp_protocol = ip->ip_p; 435646Ssam ripdst.sin_addr = ip->ip_dst; 445646Ssam ripsrc.sin_addr = ip->ip_src; 456529Ssam raw_input(m, &ripproto, (struct sockaddr *)&ripsrc, 466529Ssam (struct sockaddr *)&ripdst); 475123Swnj } 485123Swnj 495612Swnj /* 505612Swnj * Generate IP header and pass packet to ip_output. 515612Swnj * Tack on options user may have setup with control call. 525612Swnj */ 535612Swnj rip_output(m0, so) 545612Swnj struct mbuf *m0; 555612Swnj struct socket *so; 565123Swnj { 575612Swnj register struct mbuf *m; 585612Swnj register struct ip *ip; 596509Ssam int len = 0, error; 606509Ssam struct rawcb *rp = sotorawcb(so); 617156Swnj struct sockaddr_in *sin; 625123Swnj 635612Swnj /* 645612Swnj * Calculate data length and get an mbuf 655612Swnj * for IP header. 665612Swnj */ 675612Swnj for (m = m0; m; m = m->m_next) 685612Swnj len += m->m_len; 699642Ssam m = m_get(M_DONTWAIT, MT_HEADER); 705612Swnj if (m == 0) { 716509Ssam error = ENOBUFS; 726509Ssam goto bad; 735612Swnj } 745612Swnj 755612Swnj /* 765612Swnj * Fill in IP header as needed. 775612Swnj */ 785612Swnj m->m_off = MMAXOFF - sizeof(struct ip); 795612Swnj m->m_len = sizeof(struct ip); 805612Swnj m->m_next = m0; 815612Swnj ip = mtod(m, struct ip *); 8216798Skarels ip->ip_tos = 0; 8315714Skarels ip->ip_off = 0; 8421770Skarels ip->ip_p = rp->rcb_proto.sp_protocol; 855612Swnj ip->ip_len = sizeof(struct ip) + len; 867156Swnj if (rp->rcb_flags & RAW_LADDR) { 877156Swnj sin = (struct sockaddr_in *)&rp->rcb_laddr; 887156Swnj if (sin->sin_family != AF_INET) { 896509Ssam error = EAFNOSUPPORT; 906509Ssam goto bad; 916509Ssam } 927156Swnj ip->ip_src.s_addr = sin->sin_addr.s_addr; 937156Swnj } else 947156Swnj ip->ip_src.s_addr = 0; 957156Swnj ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; 965612Swnj ip->ip_ttl = MAXTTL; 97*26037Skarels return (ip_output(m, rp->rcb_options, &rp->rcb_route, 98*26037Skarels (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); 996509Ssam bad: 1006509Ssam m_freem(m); 1016509Ssam return (error); 1025123Swnj } 103*26037Skarels 104*26037Skarels /* 105*26037Skarels * Raw IP socket option processing. 106*26037Skarels */ 107*26037Skarels rip_ctloutput(op, so, level, optname, m) 108*26037Skarels int op; 109*26037Skarels struct socket *so; 110*26037Skarels int level, optname; 111*26037Skarels struct mbuf **m; 112*26037Skarels { 113*26037Skarels int error = 0; 114*26037Skarels register struct rawcb *rp = sotorawcb(so); 115*26037Skarels 116*26037Skarels if (level != IPPROTO_IP) 117*26037Skarels error = EINVAL; 118*26037Skarels else switch (op) { 119*26037Skarels 120*26037Skarels case PRCO_SETOPT: 121*26037Skarels switch (optname) { 122*26037Skarels case IP_OPTIONS: 123*26037Skarels return (ip_pcbopts(&rp->rcb_options, *m)); 124*26037Skarels 125*26037Skarels default: 126*26037Skarels error = EINVAL; 127*26037Skarels break; 128*26037Skarels } 129*26037Skarels break; 130*26037Skarels 131*26037Skarels case PRCO_GETOPT: 132*26037Skarels switch (optname) { 133*26037Skarels case IP_OPTIONS: 134*26037Skarels *m = m_get(M_WAIT, MT_SOOPTS); 135*26037Skarels if (rp->rcb_options) { 136*26037Skarels (*m)->m_off = rp->rcb_options->m_off; 137*26037Skarels (*m)->m_len = rp->rcb_options->m_len; 138*26037Skarels bcopy(mtod(rp->rcb_options, caddr_t), 139*26037Skarels mtod(*m, caddr_t), (*m)->m_len); 140*26037Skarels } else 141*26037Skarels (*m)->m_len = 0; 142*26037Skarels break; 143*26037Skarels default: 144*26037Skarels error = EINVAL; 145*26037Skarels break; 146*26037Skarels } 147*26037Skarels break; 148*26037Skarels } 149*26037Skarels if (op == PRCO_SETOPT) 150*26037Skarels m_free(*m); 151*26037Skarels return (error); 152*26037Skarels } 153