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 * 1241486Smckusick * from: Utah $Hdr: hpux_net.c 1.33 89/08/23$ 1341486Smckusick * 14*45816Smckusick * @(#)hpux_net.c 7.6 (Berkeley) 12/16/90 1541486Smckusick */ 1641486Smckusick 1741486Smckusick /* 1841486Smckusick * Network related HP-UX compatibility routines 1941486Smckusick */ 2041486Smckusick 2141486Smckusick #ifdef HPUXCOMPAT 2241486Smckusick 2345788Sbostic #include "sys/param.h" 2445788Sbostic #include "sys/systm.h" 2545788Sbostic #include "sys/kernel.h" 2645788Sbostic #include "sys/time.h" 2745788Sbostic #include "sys/errno.h" 2845788Sbostic #include "sys/proc.h" 2945788Sbostic #include "sys/file.h" 3045788Sbostic #include "sys/mbuf.h" 3145788Sbostic #include "sys/socket.h" 3245788Sbostic #include "sys/socketvar.h" 3345788Sbostic #include "sys/uio.h" 3445788Sbostic #include "sys/ktrace.h" 35*45816Smckusick #include "hpux.h" 3641486Smckusick 3741486Smckusick #define MINBSDIPCCODE 0x3EE 3841486Smckusick #define NUMBSDIPC 32 3941486Smckusick 4041486Smckusick /* 4141486Smckusick * HPUX netioctl() to BSD syscall map. 4241486Smckusick * Indexed by callno - MINBSDIPCCODE 4341486Smckusick */ 4445054Skarels extern int socket(), listen(), bind(), oaccept(), connect(), orecv(); 4545054Skarels extern int osend(), shutdown(), ogetsockname(), sendto(); 4645054Skarels extern int orecvfrom(), ogetpeername(); 4741486Smckusick int hpuxgetsockopt(), hpuxsetsockopt(); 4841486Smckusick struct file *getsock(); 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 */ 7643453Shibler hpuxnetioctl(p, uap, retval) 7743453Shibler struct proc *p; 7843453Shibler struct args { 7941486Smckusick int call; 8041486Smckusick int *args; 8143453Shibler } *uap; 8243453Shibler int *retval; 8343453Shibler { 8441486Smckusick int *args, i; 8541486Smckusick register int code; 8643453Shibler int error; 8741486Smckusick 8841486Smckusick args = uap->args; 8941486Smckusick code = uap->call - MINBSDIPCCODE; 9043453Shibler if (code < 0 || code >= NUMBSDIPC || hpuxtobsdipc[code].rout == NULL) 9144421Skarels return (EINVAL); 9241486Smckusick if ((i = hpuxtobsdipc[code].nargs * sizeof (int)) && 9343453Shibler (error = copyin((caddr_t)args, (caddr_t)uap, (u_int)i))) { 9441486Smckusick #ifdef KTRACE 9543453Shibler if (KTRPOINT(p, KTR_SYSCALL)) 9643453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 9741486Smckusick hpuxtobsdipc[code].nargs); 9841486Smckusick #endif 9944421Skarels return (error); 10041486Smckusick } 10141486Smckusick #ifdef KTRACE 10243453Shibler if (KTRPOINT(p, KTR_SYSCALL)) 10343453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE, 10441486Smckusick hpuxtobsdipc[code].nargs); 10541486Smckusick #endif 10644421Skarels return ((*hpuxtobsdipc[code].rout)(p, uap, retval)); 10741486Smckusick } 10841486Smckusick 10943453Shibler hpuxsetsockopt(p, uap, retval) 11043453Shibler struct proc *p; 11143453Shibler struct args { 11241486Smckusick int s; 11341486Smckusick int level; 11441486Smckusick int name; 11541486Smckusick caddr_t val; 11641486Smckusick int valsize; 11743453Shibler } *uap; 11843453Shibler int *retval; 11943453Shibler { 12041486Smckusick struct file *fp; 12141486Smckusick struct mbuf *m = NULL; 12243453Shibler int tmp, error; 12341486Smckusick 12443453Shibler fp = getsock(uap->s, &error); 12541486Smckusick if (fp == 0) 12644421Skarels return (error); 12743453Shibler if (uap->valsize > MLEN) 12844421Skarels return (EINVAL); 12941486Smckusick if (uap->val) { 13041486Smckusick m = m_get(M_WAIT, MT_SOOPTS); 13143453Shibler if (m == NULL) 13244421Skarels return (ENOBUFS); 13343453Shibler if (error = copyin(uap->val, mtod(m, caddr_t), 13443453Shibler (u_int)uap->valsize)) { 13541486Smckusick (void) m_free(m); 13644421Skarels return (error); 13741486Smckusick } 13841486Smckusick if (uap->name == SO_LINGER) { 13941486Smckusick tmp = *mtod(m, int *); 14041486Smckusick mtod(m, struct linger *)->l_onoff = 1; 14141486Smckusick mtod(m, struct linger *)->l_linger = tmp; 14241486Smckusick m->m_len = sizeof(struct linger); 14341486Smckusick } else 14441486Smckusick m->m_len = uap->valsize; 14541486Smckusick } else if (uap->name == ~SO_LINGER) { 14641486Smckusick m = m_get(M_WAIT, MT_SOOPTS); 14741486Smckusick if (m) { 14841486Smckusick uap->name = SO_LINGER; 14941486Smckusick mtod(m, struct linger *)->l_onoff = 0; 15041486Smckusick m->m_len = sizeof(struct linger); 15141486Smckusick } 15241486Smckusick } 15344421Skarels return (sosetopt((struct socket *)fp->f_data, uap->level, 15443453Shibler uap->name, m)); 15541486Smckusick } 15641486Smckusick 15743453Shibler hpuxgetsockopt(p, uap, retval) 15843453Shibler struct proc *p; 15943453Shibler struct args { 16041486Smckusick int s; 16141486Smckusick int level; 16241486Smckusick int name; 16341486Smckusick caddr_t val; 16441486Smckusick int *avalsize; 16543453Shibler } *uap; 16643453Shibler int *retval; 16743453Shibler { 16841486Smckusick struct file *fp; 16941486Smckusick struct mbuf *m = NULL; 17043453Shibler int valsize, error; 17141486Smckusick 17243453Shibler fp = getsock(uap->s, &error); 17341486Smckusick if (fp == 0) 17444421Skarels return (error); 17541486Smckusick if (uap->val) { 17643453Shibler if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize, 17743453Shibler sizeof (valsize))) 17844421Skarels return (error); 17941486Smckusick } else 18041486Smckusick valsize = 0; 18143453Shibler if (error = sogetopt((struct socket *)fp->f_data, uap->level, 18243453Shibler uap->name, &m)) 18341486Smckusick goto bad; 18441486Smckusick if (uap->val && valsize && m != NULL) { 18541486Smckusick if (uap->name == SO_LINGER) { 18641486Smckusick if (mtod(m, struct linger *)->l_onoff) 18741486Smckusick *mtod(m, int *) = mtod(m, struct linger *)->l_linger; 18841486Smckusick else 18941486Smckusick *mtod(m, int *) = 0; 19041486Smckusick m->m_len = sizeof(int); 19141486Smckusick } 19241486Smckusick if (valsize > m->m_len) 19341486Smckusick valsize = m->m_len; 19443453Shibler error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize); 19543453Shibler if (error == 0) 19643453Shibler error = copyout((caddr_t)&valsize, 19743453Shibler (caddr_t)uap->avalsize, sizeof (valsize)); 19841486Smckusick } 19941486Smckusick bad: 20041486Smckusick if (m != NULL) 20141486Smckusick (void) m_free(m); 20244421Skarels return (error); 20341486Smckusick } 20441486Smckusick #endif 205