1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1990 The Regents of the University of California. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * the Systems Programming Group of the University of Utah Computer 8 * Science Department. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: hpux_net.c 1.33 89/08/23$ 13 * 14 * @(#)hpux_net.c 7.1 (Berkeley) 05/08/90 15 */ 16 17 /* 18 * Network related HP-UX compatibility routines 19 */ 20 21 #ifdef HPUXCOMPAT 22 23 #include "param.h" 24 #include "systm.h" 25 #include "user.h" 26 #include "kernel.h" 27 #include "proc.h" 28 #include "file.h" 29 #include "mbuf.h" 30 #include "socket.h" 31 #include "socketvar.h" 32 #include "ktrace.h" 33 #include "hpux.h" 34 35 #define MINBSDIPCCODE 0x3EE 36 #define NUMBSDIPC 32 37 38 /* 39 * HPUX netioctl() to BSD syscall map. 40 * Indexed by callno - MINBSDIPCCODE 41 */ 42 extern int socket(), listen(), bind(), accept(), connect(), orecv(); 43 extern int osend(), shutdown(), getsockname(), sendto(); 44 extern int recvfrom(), getpeername(); 45 int hpuxgetsockopt(), hpuxsetsockopt(); 46 struct file *getsock(); 47 48 struct hpuxtobsdipc { 49 int (*rout)(); 50 int nargs; 51 } hpuxtobsdipc[NUMBSDIPC] = { 52 socket, 3, /* 3ee */ listen, 2, /* 3ef */ 53 bind, 3, /* 3f0 */ accept, 3, /* 3f1 */ 54 connect, 3, /* 3f2 */ orecv, 4, /* 3f3 */ 55 osend, 4, /* 3f4 */ shutdown, 2, /* 3f5 */ 56 getsockname, 3, /* 3f6 */ hpuxsetsockopt, 5, /* 3f7 */ 57 sendto, 6, /* 3f8 */ recvfrom, 6, /* 3f9 */ 58 getpeername, 3, /* 3fa */ NULL, 0, /* 3fb */ 59 NULL, 0, /* 3fc */ NULL, 0, /* 3fd */ 60 NULL, 0, /* 3fe */ NULL, 0, /* 3ff */ 61 NULL, 0, /* 400 */ NULL, 0, /* 401 */ 62 NULL, 0, /* 402 */ NULL, 0, /* 403 */ 63 NULL, 0, /* 404 */ NULL, 0, /* 405 */ 64 NULL, 0, /* 406 */ NULL, 0, /* 407 */ 65 NULL, 0, /* 408 */ NULL, 0, /* 409 */ 66 NULL, 0, /* 40a */ hpuxgetsockopt, 5, /* 40b */ 67 NULL, 0, /* 40c */ NULL, 0, /* 40d */ 68 }; 69 70 /* 71 * Single system call entry to BSD style IPC. 72 * Gleened from disassembled libbsdipc.a syscall entries. 73 */ 74 hpuxnetioctl() 75 { 76 struct a { 77 int call; 78 int *args; 79 } *uap = (struct a *)u.u_ap; 80 int *args, i; 81 register int code; 82 83 args = uap->args; 84 code = uap->call - MINBSDIPCCODE; 85 if (code < 0 || code >= NUMBSDIPC || hpuxtobsdipc[code].rout == NULL) { 86 u.u_error = EINVAL; 87 return; 88 } 89 if ((i = hpuxtobsdipc[code].nargs * sizeof (int)) && 90 (u.u_error = copyin((caddr_t)args, (caddr_t)u.u_arg, (u_int)i))) { 91 #ifdef KTRACE 92 if (KTRPOINT(u.u_procp, KTR_SYSCALL)) 93 ktrsyscall(u.u_procp->p_tracep, code + MINBSDIPCCODE, 94 hpuxtobsdipc[code].nargs); 95 #endif 96 return; 97 } 98 #ifdef KTRACE 99 if (KTRPOINT(u.u_procp, KTR_SYSCALL)) 100 ktrsyscall(u.u_procp->p_tracep, code + MINBSDIPCCODE, 101 hpuxtobsdipc[code].nargs); 102 #endif 103 (*hpuxtobsdipc[code].rout)(); 104 } 105 106 hpuxsetsockopt() 107 { 108 struct a { 109 int s; 110 int level; 111 int name; 112 caddr_t val; 113 int valsize; 114 } *uap = (struct a *)u.u_ap; 115 struct file *fp; 116 struct mbuf *m = NULL; 117 int tmp; 118 119 fp = getsock(uap->s); 120 if (fp == 0) 121 return; 122 if (uap->valsize > MLEN) { 123 u.u_error = EINVAL; 124 return; 125 } 126 if (uap->val) { 127 m = m_get(M_WAIT, MT_SOOPTS); 128 if (m == NULL) { 129 u.u_error = ENOBUFS; 130 return; 131 } 132 u.u_error = 133 copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize); 134 if (u.u_error) { 135 (void) m_free(m); 136 return; 137 } 138 if (uap->name == SO_LINGER) { 139 tmp = *mtod(m, int *); 140 mtod(m, struct linger *)->l_onoff = 1; 141 mtod(m, struct linger *)->l_linger = tmp; 142 m->m_len = sizeof(struct linger); 143 } else 144 m->m_len = uap->valsize; 145 } else if (uap->name == ~SO_LINGER) { 146 m = m_get(M_WAIT, MT_SOOPTS); 147 if (m) { 148 uap->name = SO_LINGER; 149 mtod(m, struct linger *)->l_onoff = 0; 150 m->m_len = sizeof(struct linger); 151 } 152 } 153 u.u_error = 154 sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m); 155 } 156 157 hpuxgetsockopt() 158 { 159 struct a { 160 int s; 161 int level; 162 int name; 163 caddr_t val; 164 int *avalsize; 165 } *uap = (struct a *)u.u_ap; 166 struct file *fp; 167 struct mbuf *m = NULL; 168 int valsize; 169 170 fp = getsock(uap->s); 171 if (fp == 0) 172 return; 173 if (uap->val) { 174 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 175 sizeof (valsize)); 176 if (u.u_error) 177 return; 178 } else 179 valsize = 0; 180 u.u_error = 181 sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m); 182 if (u.u_error) 183 goto bad; 184 if (uap->val && valsize && m != NULL) { 185 if (uap->name == SO_LINGER) { 186 if (mtod(m, struct linger *)->l_onoff) 187 *mtod(m, int *) = mtod(m, struct linger *)->l_linger; 188 else 189 *mtod(m, int *) = 0; 190 m->m_len = sizeof(int); 191 } 192 if (valsize > m->m_len) 193 valsize = m->m_len; 194 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 195 if (u.u_error) 196 goto bad; 197 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize, 198 sizeof (valsize)); 199 } 200 bad: 201 if (m != NULL) 202 (void) m_free(m); 203 } 204 #endif 205