141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 341486Smckusick * Copyright (c) 1990 The Regents of the University of California. 441486Smckusick * All rights reserved. 541486Smckusick * 641486Smckusick * This code is derived from software contributed to Berkeley by 741486Smckusick * the Systems Programming Group of the University of Utah Computer 841486Smckusick * Science Department. 941486Smckusick * 1041486Smckusick * %sccs.include.redist.c% 1141486Smckusick * 12*57307Shibler * from: Utah $Hdr: hpux_net.c 1.6 92/12/26$ 1341486Smckusick * 14*57307Shibler * @(#)hpux_net.c 7.9 (Berkeley) 12/27/92 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Network related HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2356506Sbostic #include <sys/param.h> 2456506Sbostic #include <sys/systm.h> 2556506Sbostic #include <sys/kernel.h> 2656506Sbostic #include <sys/time.h> 2756506Sbostic #include <sys/errno.h> 2856506Sbostic #include <sys/proc.h> 2956506Sbostic #include <sys/file.h> 3056506Sbostic #include <sys/mbuf.h> 3156506Sbostic #include <sys/socket.h> 3256506Sbostic #include <sys/socketvar.h> 3356506Sbostic #include <sys/uio.h> 3456506Sbostic #include <sys/ktrace.h> 3541486Smckusick 3656506Sbostic #include <hp/hpux/hpux.h> 3756506Sbostic 3841486Smckusick #define MINBSDIPCCODE 0x3EE 3941486Smckusick #define NUMBSDIPC 32 4041486Smckusick 4141486Smckusick /* 4241486Smckusick * HPUX netioctl() to BSD syscall map. 4341486Smckusick * Indexed by callno - MINBSDIPCCODE 4441486Smckusick */ 4545054Skarels extern int socket(), listen(), bind(), oaccept(), connect(), orecv(); 4645054Skarels extern int osend(), shutdown(), ogetsockname(), sendto(); 4745054Skarels extern int orecvfrom(), ogetpeername(); 4841486Smckusick int hpuxgetsockopt(), hpuxsetsockopt(); 4941486Smckusick 5041486Smckusick struct hpuxtobsdipc { 5141486Smckusick int (*rout)(); 5241486Smckusick int nargs; 5341486Smckusick } hpuxtobsdipc[NUMBSDIPC] = { 5441486Smckusick socket, 3, /* 3ee */ listen, 2, /* 3ef */ 5545054Skarels bind, 3, /* 3f0 */ oaccept, 3, /* 3f1 */ 5641486Smckusick connect, 3, /* 3f2 */ orecv, 4, /* 3f3 */ 5741486Smckusick osend, 4, /* 3f4 */ shutdown, 2, /* 3f5 */ 5845054Skarels ogetsockname, 3, /* 3f6 */ hpuxsetsockopt, 5, /* 3f7 */ 5945054Skarels sendto, 6, /* 3f8 */ orecvfrom, 6, /* 3f9 */ 6045054Skarels ogetpeername, 3, /* 3fa */ NULL, 0, /* 3fb */ 6141486Smckusick NULL, 0, /* 3fc */ NULL, 0, /* 3fd */ 6241486Smckusick NULL, 0, /* 3fe */ NULL, 0, /* 3ff */ 6341486Smckusick NULL, 0, /* 400 */ NULL, 0, /* 401 */ 6441486Smckusick NULL, 0, /* 402 */ NULL, 0, /* 403 */ 6541486Smckusick NULL, 0, /* 404 */ NULL, 0, /* 405 */ 6641486Smckusick NULL, 0, /* 406 */ NULL, 0, /* 407 */ 6741486Smckusick NULL, 0, /* 408 */ NULL, 0, /* 409 */ 6841486Smckusick NULL, 0, /* 40a */ hpuxgetsockopt, 5, /* 40b */ 6941486Smckusick NULL, 0, /* 40c */ NULL, 0, /* 40d */ 7041486Smckusick }; 7141486Smckusick 7241486Smckusick /* 7341486Smckusick * Single system call entry to BSD style IPC. 7441486Smckusick * Gleened from disassembled libbsdipc.a syscall entries. 7541486Smckusick */ 76*57307Shibler struct hpuxnetioctl_args { 77*57307Shibler int call; 78*57307Shibler int *args; 79*57307Shibler }; 8043453Shibler hpuxnetioctl(p, uap, retval) 8143453Shibler struct proc *p; 82*57307Shibler struct hpuxnetioctl_args *uap; 8343453Shibler int *retval; 8443453Shibler { 8541486Smckusick int *args, i; 8641486Smckusick register int code; 8743453Shibler int error; 8841486Smckusick 8941486Smckusick args = uap->args; 9041486Smckusick code = uap->call - MINBSDIPCCODE; 9143453Shibler if (code < 0 || code >= NUMBSDIPC || hpuxtobsdipc[code].rout == NULL) 9244421Skarels return (EINVAL); 9341486Smckusick if ((i = hpuxtobsdipc[code].nargs * sizeof (int)) && 9443453Shibler (error = copyin((caddr_t)args, (caddr_t)uap, (u_int)i))) { 9541486Smckusick #ifdef KTRACE 9643453Shibler if (KTRPOINT(p, KTR_SYSCALL)) 9743453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 9841486Smckusick hpuxtobsdipc[code].nargs); 9941486Smckusick #endif 10044421Skarels return (error); 10141486Smckusick } 10241486Smckusick #ifdef KTRACE 10343453Shibler if (KTRPOINT(p, KTR_SYSCALL)) 10443453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 10541486Smckusick hpuxtobsdipc[code].nargs); 10641486Smckusick #endif 10744421Skarels return ((*hpuxtobsdipc[code].rout)(p, uap, retval)); 10841486Smckusick } 10941486Smckusick 110*57307Shibler socksetsize(size, m) 111*57307Shibler int size; 112*57307Shibler struct mbuf *m; 113*57307Shibler { 114*57307Shibler register int tmp; 115*57307Shibler 116*57307Shibler if (size < sizeof(int)) { 117*57307Shibler switch(size) { 118*57307Shibler case 1: 119*57307Shibler tmp = (int) *mtod(m, char *); 120*57307Shibler break; 121*57307Shibler case 2: 122*57307Shibler tmp = (int) *mtod(m, short *); 123*57307Shibler break; 124*57307Shibler case 3: 125*57307Shibler tmp = (((int) *mtod(m, int *)) >> 8) & 0xffffff; 126*57307Shibler break; 127*57307Shibler } 128*57307Shibler *mtod(m, int *) = tmp; 129*57307Shibler m->m_len = sizeof(int); 130*57307Shibler } else { 131*57307Shibler m->m_len = size; 132*57307Shibler } 133*57307Shibler } 134*57307Shibler 135*57307Shibler struct hpuxsetsockopt_args { 136*57307Shibler int s; 137*57307Shibler int level; 138*57307Shibler int name; 139*57307Shibler caddr_t val; 140*57307Shibler int valsize; 141*57307Shibler }; 142*57307Shibler /* ARGSUSED */ 14343453Shibler hpuxsetsockopt(p, uap, retval) 14443453Shibler struct proc *p; 145*57307Shibler struct hpuxsetsockopt_args *uap; 14643453Shibler int *retval; 14743453Shibler { 14841486Smckusick struct file *fp; 14941486Smckusick struct mbuf *m = NULL; 15043453Shibler int tmp, error; 15141486Smckusick 15246403Smckusick if (error = getsock(p->p_fd, uap->s, &fp)) 15344421Skarels return (error); 15443453Shibler if (uap->valsize > MLEN) 15544421Skarels return (EINVAL); 15641486Smckusick if (uap->val) { 15741486Smckusick m = m_get(M_WAIT, MT_SOOPTS); 15843453Shibler if (m == NULL) 15944421Skarels return (ENOBUFS); 16043453Shibler if (error = copyin(uap->val, mtod(m, caddr_t), 16143453Shibler (u_int)uap->valsize)) { 16241486Smckusick (void) m_free(m); 16344421Skarels return (error); 16441486Smckusick } 16541486Smckusick if (uap->name == SO_LINGER) { 16641486Smckusick tmp = *mtod(m, int *); 16741486Smckusick mtod(m, struct linger *)->l_onoff = 1; 16841486Smckusick mtod(m, struct linger *)->l_linger = tmp; 16941486Smckusick m->m_len = sizeof(struct linger); 17041486Smckusick } else 171*57307Shibler socksetsize(uap->valsize, m); 17241486Smckusick } else if (uap->name == ~SO_LINGER) { 17341486Smckusick m = m_get(M_WAIT, MT_SOOPTS); 17441486Smckusick if (m) { 17541486Smckusick uap->name = SO_LINGER; 17641486Smckusick mtod(m, struct linger *)->l_onoff = 0; 17741486Smckusick m->m_len = sizeof(struct linger); 17841486Smckusick } 17941486Smckusick } 18044421Skarels return (sosetopt((struct socket *)fp->f_data, uap->level, 18143453Shibler uap->name, m)); 18241486Smckusick } 18341486Smckusick 184*57307Shibler struct hpuxsetsockopt2_args { 185*57307Shibler int s; 186*57307Shibler int level; 187*57307Shibler int name; 188*57307Shibler caddr_t val; 189*57307Shibler int valsize; 190*57307Shibler }; 191*57307Shibler /* ARGSUSED */ 192*57307Shibler hpuxsetsockopt2(p, uap, retval) 193*57307Shibler struct proc *p; 194*57307Shibler register struct hpuxsetsockopt2_args *uap; 195*57307Shibler int *retval; 196*57307Shibler { 197*57307Shibler struct file *fp; 198*57307Shibler struct mbuf *m = NULL; 199*57307Shibler int error; 200*57307Shibler 201*57307Shibler if (error = getsock(p->p_fd, uap->s, &fp)) 202*57307Shibler return (error); 203*57307Shibler if (uap->valsize > MLEN) 204*57307Shibler return (EINVAL); 205*57307Shibler if (uap->val) { 206*57307Shibler m = m_get(M_WAIT, MT_SOOPTS); 207*57307Shibler if (m == NULL) 208*57307Shibler return (ENOBUFS); 209*57307Shibler if (error = copyin(uap->val, mtod(m, caddr_t), 210*57307Shibler (u_int)uap->valsize)) { 211*57307Shibler (void) m_free(m); 212*57307Shibler return (error); 213*57307Shibler } 214*57307Shibler socksetsize(uap->valsize, m); 215*57307Shibler } 216*57307Shibler return (sosetopt((struct socket *)fp->f_data, uap->level, 217*57307Shibler uap->name, m)); 218*57307Shibler } 219*57307Shibler 220*57307Shibler struct hpuxgetsockopt_args { 221*57307Shibler int s; 222*57307Shibler int level; 223*57307Shibler int name; 224*57307Shibler caddr_t val; 225*57307Shibler int *avalsize; 226*57307Shibler }; 22743453Shibler hpuxgetsockopt(p, uap, retval) 22843453Shibler struct proc *p; 229*57307Shibler struct hpuxgetsockopt_args *uap; 23043453Shibler int *retval; 23143453Shibler { 23241486Smckusick struct file *fp; 23341486Smckusick struct mbuf *m = NULL; 23443453Shibler int valsize, error; 23541486Smckusick 23646403Smckusick if (error = getsock(p->p_fd, uap->s, &fp)) 23744421Skarels return (error); 23841486Smckusick if (uap->val) { 23943453Shibler if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 24043453Shibler sizeof (valsize))) 24144421Skarels return (error); 24241486Smckusick } else 24341486Smckusick valsize = 0; 24443453Shibler if (error = sogetopt((struct socket *)fp->f_data, uap->level, 24543453Shibler uap->name, &m)) 24641486Smckusick goto bad; 24741486Smckusick if (uap->val && valsize && m != NULL) { 24841486Smckusick if (uap->name == SO_LINGER) { 24941486Smckusick if (mtod(m, struct linger *)->l_onoff) 25041486Smckusick *mtod(m, int *) = mtod(m, struct linger *)->l_linger; 25141486Smckusick else 25241486Smckusick *mtod(m, int *) = 0; 25341486Smckusick m->m_len = sizeof(int); 25441486Smckusick } 25541486Smckusick if (valsize > m->m_len) 25641486Smckusick valsize = m->m_len; 25743453Shibler error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 25843453Shibler if (error == 0) 25943453Shibler error = copyout((caddr_t)&valsize, 26043453Shibler (caddr_t)uap->avalsize, sizeof (valsize)); 26141486Smckusick } 26241486Smckusick bad: 26341486Smckusick if (m != NULL) 26441486Smckusick (void) m_free(m); 26544421Skarels return (error); 26641486Smckusick } 26741486Smckusick #endif 268