1 /* raw_imp.c 4.8 82/03/13 */ 2 3 #include "../h/param.h" 4 #include "../h/mbuf.h" 5 #include "../h/socket.h" 6 #include "../h/protosw.h" 7 #include "../h/socketvar.h" 8 #include "../net/in.h" 9 #include "../net/in_systm.h" 10 #include "../net/if.h" 11 #include "../net/if_imp.h" 12 #include "../net/raw_cb.h" 13 #include "../errno.h" 14 15 /* 16 * Raw interface to IMP. 17 */ 18 19 /*ARGSUSED*/ 20 rimp_ctlinput(m) 21 struct mbuf *m; 22 { 23 COUNT(RIMP_CTLINPUT); 24 } 25 26 /* 27 * Generate IMP leader and pass packet to impoutput. 28 * The user must create a skeletal leader in order to 29 * communicate message type, message subtype, etc. 30 * We fill in holes where needed and verify parameters 31 * supplied by user. 32 */ 33 rimp_output(m, so) 34 register struct mbuf *m; 35 struct socket *so; 36 { 37 struct mbuf *n; 38 int len; 39 register struct imp_leader *ip; 40 register struct sockaddr_in *sin; 41 register struct rawcb *rp = sotorawcb(so); 42 struct ifnet *ifp; 43 struct control_leader *cp; 44 45 COUNT(RIMP_OUTPUT); 46 /* 47 * Verify user has supplied necessary space 48 * for the leader and check parameters in it. 49 */ 50 if ((m->m_off > MMAXOFF || m->m_len < sizeof(struct control_leader)) && 51 (m = m_pullup(m, sizeof(struct control_leader))) == 0) 52 return (0); 53 cp = mtod(m, struct control_leader *); 54 if (cp->dl_mtype == IMPTYPE_DATA) 55 if (m->m_len < sizeof(struct imp_leader) && 56 (m = m_pullup(m, sizeof(struct imp_leader))) == 0) 57 return (0); 58 ip = mtod(m, struct imp_leader *); 59 if (ip->il_format != IMP_NFF) 60 goto bad; 61 #ifdef notdef 62 if (ip->il_link != IMPLINK_IP && 63 (ip->il_link < IMPLINK_LOWEXPER || ip->il_link > IMPLINK_HIGHEXPER)) 64 goto bad; 65 #endif 66 67 /* 68 * Fill in IMP leader -- impoutput refrains from rebuilding 69 * the leader when it sees the protocol family PF_IMPLINK. 70 * (message size calculated by walking through mbuf's) 71 */ 72 for (len = 0, n = m; n; n = n->m_next) 73 len += n->m_len; 74 ip->il_length = htons((u_short)(len << 3)); 75 sin = (struct sockaddr_in *)&rp->rcb_addr; 76 ip->il_network = sin->sin_addr.s_net; 77 ip->il_host = sin->sin_addr.s_host; 78 ip->il_imp = sin->sin_addr.s_imp; 79 ifp = if_ifonnetof(sin->sin_addr); 80 if (ifp == 0) { 81 ifp = if_gatewayfor(sin->sin_addr); 82 if (ifp == 0) 83 goto bad; 84 } 85 return (impoutput(ifp, m, PF_IMPLINK)); 86 87 bad: 88 m_freem(m); 89 return (0); 90 } 91 92 /* 93 * Intercept operations required to 94 * maintain interface pointer used on output. 95 */ 96 rimp_usrreq(so, req, m, addr) 97 struct socket *so; 98 int req; 99 struct mbuf *m; 100 caddr_t addr; 101 { 102 register struct rawcb *rp = sotorawcb(so); 103 register struct sockaddr_in *sin; 104 register struct ifnet *ifp; 105 106 COUNT(RIMP_USRREQ); 107 if (rp == 0 && req != PRU_ATTACH) 108 return (EINVAL); 109 110 switch (req) { 111 112 /* 113 * Verify address has an interface to go with it. 114 */ 115 case PRU_CONNECT: 116 if (rp->rcb_pcb) 117 return (EISCONN); 118 sin = (struct sockaddr_in *)addr; 119 ifp = if_ifonnetof(sin->sin_addr); 120 if (ifp == 0) { 121 ifp = if_gatewayfor(sin->sin_addr); 122 if (ifp == 0) 123 return (EADDRNOTAVAIL); /* XXX */ 124 } 125 rp->rcb_pcb = (caddr_t)ifp; 126 break; 127 128 case PRU_DISCONNECT: 129 rp->rcb_pcb = 0; 130 break; 131 132 case PRU_CONTROL: 133 return (EOPNOTSUPP); 134 } 135 return (raw_usrreq(so, req, m, addr)); 136 } 137