141486Smckusick /* 241486Smckusick * Copyright (c) 1988 University of Utah. 363148Sbostic * Copyright (c) 1990, 1993 463148Sbostic * The Regents of the University of California. 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*64477Shibler * from: Utah $Hdr: hpux_net.c 1.8 93/08/02$ 1341486Smckusick * 14*64477Shibler * @(#)hpux_net.c 8.2 (Berkeley) 09/09/93 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 */ 7657307Shibler struct hpuxnetioctl_args { 7757307Shibler int call; 7857307Shibler int *args; 7957307Shibler }; 8043453Shibler hpuxnetioctl(p, uap, retval) 8143453Shibler struct proc *p; 8257307Shibler 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, 98*64477Shibler hpuxtobsdipc[code].nargs, (int *)uap); 9941486Smckusick #endif 10044421Skarels return (error); 10141486Smckusick } 10241486Smckusick #ifdef KTRACE 10343453Shibler if (KTRPOINT(p, KTR_SYSCALL)) 10443453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 105*64477Shibler hpuxtobsdipc[code].nargs, (int *)uap); 10641486Smckusick #endif 10744421Skarels return ((*hpuxtobsdipc[code].rout)(p, uap, retval)); 10841486Smckusick } 10941486Smckusick 11057307Shibler socksetsize(size, m) 11157307Shibler int size; 11257307Shibler struct mbuf *m; 11357307Shibler { 11457307Shibler register int tmp; 11557307Shibler 11657307Shibler if (size < sizeof(int)) { 11757307Shibler switch(size) { 11857307Shibler case 1: 11957307Shibler tmp = (int) *mtod(m, char *); 12057307Shibler break; 12157307Shibler case 2: 12257307Shibler tmp = (int) *mtod(m, short *); 12357307Shibler break; 12457307Shibler case 3: 12557307Shibler tmp = (((int) *mtod(m, int *)) >> 8) & 0xffffff; 12657307Shibler break; 12757307Shibler } 12857307Shibler *mtod(m, int *) = tmp; 12957307Shibler m->m_len = sizeof(int); 13057307Shibler } else { 13157307Shibler m->m_len = size; 13257307Shibler } 13357307Shibler } 13457307Shibler 13557307Shibler struct hpuxsetsockopt_args { 13657307Shibler int s; 13757307Shibler int level; 13857307Shibler int name; 13957307Shibler caddr_t val; 14057307Shibler int valsize; 14157307Shibler }; 14257307Shibler /* ARGSUSED */ 14343453Shibler hpuxsetsockopt(p, uap, retval) 14443453Shibler struct proc *p; 14557307Shibler 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 17157307Shibler 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 18457307Shibler struct hpuxsetsockopt2_args { 18557307Shibler int s; 18657307Shibler int level; 18757307Shibler int name; 18857307Shibler caddr_t val; 18957307Shibler int valsize; 19057307Shibler }; 19157307Shibler /* ARGSUSED */ 19257307Shibler hpuxsetsockopt2(p, uap, retval) 19357307Shibler struct proc *p; 19457307Shibler register struct hpuxsetsockopt2_args *uap; 19557307Shibler int *retval; 19657307Shibler { 19757307Shibler struct file *fp; 19857307Shibler struct mbuf *m = NULL; 19957307Shibler int error; 20057307Shibler 20157307Shibler if (error = getsock(p->p_fd, uap->s, &fp)) 20257307Shibler return (error); 20357307Shibler if (uap->valsize > MLEN) 20457307Shibler return (EINVAL); 20557307Shibler if (uap->val) { 20657307Shibler m = m_get(M_WAIT, MT_SOOPTS); 20757307Shibler if (m == NULL) 20857307Shibler return (ENOBUFS); 20957307Shibler if (error = copyin(uap->val, mtod(m, caddr_t), 21057307Shibler (u_int)uap->valsize)) { 21157307Shibler (void) m_free(m); 21257307Shibler return (error); 21357307Shibler } 21457307Shibler socksetsize(uap->valsize, m); 21557307Shibler } 21657307Shibler return (sosetopt((struct socket *)fp->f_data, uap->level, 21757307Shibler uap->name, m)); 21857307Shibler } 21957307Shibler 22057307Shibler struct hpuxgetsockopt_args { 22157307Shibler int s; 22257307Shibler int level; 22357307Shibler int name; 22457307Shibler caddr_t val; 22557307Shibler int *avalsize; 22657307Shibler }; 22743453Shibler hpuxgetsockopt(p, uap, retval) 22843453Shibler struct proc *p; 22957307Shibler 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