1 /**************************************************************************/ 2 /* */ 3 /* miscellaneous ip routines */ 4 /* */ 5 /**************************************************************************/ 6 7 8 #include "../h/param.h" 9 #include "../h/mbuf.h" 10 #include "../h/protosw.h" 11 #include "../h/socket.h" 12 #include "../h/socketvar.h" 13 #include "../h/errno.h" 14 15 #include "../net/if.h" 16 #include "../net/route.h" 17 #include "../net/af.h" 18 #include "../net/netisr.h" 19 20 #include "../vax/mtpr.h" 21 22 #include "../bbnnet/in.h" 23 #include "../bbnnet/in_var.h" 24 #include "../bbnnet/net.h" 25 #include "../bbnnet/in_pcb.h" 26 #include "../bbnnet/fsm.h" 27 #include "../bbnnet/ip.h" 28 #include "../bbnnet/icmp.h" 29 30 31 ip_ioctl (inp, command, data) 32 struct inpcb *inp; 33 int command; 34 caddr_t data; 35 { 36 /* no IP ioctls */ 37 return in_ioctl (command, data); 38 } 39 40 ip_ctloutput(req, so, level, optname, optval) 41 int req; 42 struct socket *so; 43 int level, optname; 44 struct mbuf **optval; 45 { 46 struct inpcb *inp; 47 48 /* 49 * O.K., with the berkeley method of using the protocol number for the level, 50 * what magic cookie should we use to distinguish between IP and the interfaces? 51 */ 52 inp = sotoinpcb(so); 53 54 switch(req) 55 { 56 case PRCO_GETOPT: 57 return(ip_getopt(inp,optname,optval)); 58 59 case PRCO_SETOPT: 60 return(ip_setopt(inp,optname,optval)); 61 62 default: 63 panic("ip_ctloutput"); 64 } 65 /*NOTREACHED*/ 66 } 67 68 ip_setopt (inpcb, command, data) 69 struct inpcb *inpcb; 70 struct mbuf **data; 71 { 72 register int error = 0; 73 register struct mbuf *m = *data; 74 75 switch (command) 76 { 77 case SO_IPROUTE: 78 /* this probably breaks!! */ 79 if (m->m_len == 0) 80 { 81 /* turns off use of options */ 82 inpcb->inp_optlen = 0; 83 break; 84 } 85 if ((m->m_len < (2 * sizeof(struct in_addr))) || 86 (m->m_len > (MAX_IPOPTLEN - sizeof(struct in_addr))) || 87 (m->m_len % sizeof(struct in_addr))) 88 { 89 error = EINVAL; 90 break; 91 } 92 /* 93 * O.K., user process specifies it as: 94 * ->A->B->C->D 95 * D must be our final destination (but we can't 96 * check that since we haven't connected yet). 97 * Convert this into a form for ip_output. 98 */ 99 inpcb->inp_optlen = m->m_len; 100 bcopy (mtod(m, caddr_t), inpcb->inp_options, (unsigned)m->m_len); 101 102 /* 103 * Following could be moved to ip_send(), but let's 104 * do it once for efficiency even though user may 105 * retrieve different from what stored. 106 */ 107 { 108 char *p; 109 struct in_addr *ipa; 110 111 p = inpcb->inp_options; 112 ipa = (struct in_addr *) p; 113 ipa[m->m_len / sizeof(struct in_addr)] = ipa[0]; 114 p[0] = IP_NOP_OPT; 115 p[1] = IP_LRTE_OPT; 116 p[2] = m->m_len -1; 117 p[3] = 4; /* offset: counting one based */ 118 } 119 /* 120 * Now we have a correct IP source route recorded, 121 * and the first hop comes after the source route. 122 */ 123 break; 124 default: 125 error = EINVAL; 126 } 127 128 /* they can futz with m */ 129 if (*data) 130 m_freem(*data); 131 132 return (error); 133 } 134 135 ip_getopt (inpcb, command, data) 136 struct inpcb *inpcb; 137 struct mbuf **data; 138 { 139 register error = 0; 140 register struct mbuf *m = NULL; 141 142 *data = NULL; /* o.k. (no data sent on getsockopt) */ 143 144 switch (command) 145 { 146 case SO_IPROUTE: 147 if (!inpcb->inp_optlen) 148 break; 149 150 m = m_get(M_WAIT, MT_SOOPTS); 151 152 if (m == 0) 153 return(ENOBUFS); 154 155 m->m_len = inpcb->inp_optlen; 156 157 bcopy (inpcb->inp_options, mtod(m, caddr_t), (unsigned)m->m_len); 158 break; 159 160 default: 161 error = EINVAL; 162 } 163 *data = m; 164 return (error); 165 } 166 167 u_char inetctlerrmap[PRC_NCMDS] = 168 { 169 ENETUNREACH, /* PRC_IFDOWN: connection oriented protocols use 170 * interface with their local address. Can't re-route. 171 */ 172 173 ECONNABORTED, 0, 0, 174 0, 0, EHOSTDOWN, EHOSTUNREACH, 175 ENETUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, 176 EMSGSIZE, 0, 0, 0, 177 0, 0, 0, 0 178 } ; 179