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 *
1264477Shibler * from: Utah $Hdr: hpux_net.c 1.8 93/08/02$
1341486Smckusick *
14*68374Scgd * @(#)hpux_net.c 8.3 (Berkeley) 02/19/95
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 */
45*68374Scgd extern int socket(), listen(), bind(), compat_43_accept(), connect();
46*68374Scgd extern int compat_43_recv(), compat_43_send(), shutdown();
47*68374Scgd extern int compat_43_getsockname(), sendto(), compat_43_recvfrom();
48*68374Scgd extern int compat_43_getpeername();
4941486Smckusick int hpuxgetsockopt(), hpuxsetsockopt();
5041486Smckusick
5141486Smckusick struct hpuxtobsdipc {
5241486Smckusick int (*rout)();
5341486Smckusick int nargs;
5441486Smckusick } hpuxtobsdipc[NUMBSDIPC] = {
55*68374Scgd socket, 3, /* 3ee */ listen, 2, /* 3ef */
56*68374Scgd bind, 3, /* 3f0 */ compat_43_accept, 3, /* 3f1 */
57*68374Scgd connect, 3, /* 3f2 */ compat_43_recv, 4, /* 3f3 */
58*68374Scgd compat_43_send, 4, /* 3f4 */ shutdown, 2, /* 3f5 */
59*68374Scgd compat_43_getsockname, 3, /* 3f6 */ hpuxsetsockopt, 5, /* 3f7 */
60*68374Scgd sendto, 6, /* 3f8 */ compat_43_recvfrom, 6, /* 3f9 */
61*68374Scgd compat_43_getpeername, 3, /* 3fa */ NULL, 0, /* 3fb */
62*68374Scgd NULL, 0, /* 3fc */ NULL, 0, /* 3fd */
63*68374Scgd NULL, 0, /* 3fe */ NULL, 0, /* 3ff */
64*68374Scgd NULL, 0, /* 400 */ NULL, 0, /* 401 */
65*68374Scgd NULL, 0, /* 402 */ NULL, 0, /* 403 */
66*68374Scgd NULL, 0, /* 404 */ NULL, 0, /* 405 */
67*68374Scgd NULL, 0, /* 406 */ NULL, 0, /* 407 */
68*68374Scgd NULL, 0, /* 408 */ NULL, 0, /* 409 */
69*68374Scgd NULL, 0, /* 40a */ hpuxgetsockopt, 5, /* 40b */
70*68374Scgd NULL, 0, /* 40c */ NULL, 0, /* 40d */
7141486Smckusick };
7241486Smckusick
7341486Smckusick /*
7441486Smckusick * Single system call entry to BSD style IPC.
7541486Smckusick * Gleened from disassembled libbsdipc.a syscall entries.
7641486Smckusick */
7757307Shibler struct hpuxnetioctl_args {
7857307Shibler int call;
7957307Shibler int *args;
8057307Shibler };
8143453Shibler hpuxnetioctl(p, uap, retval)
8243453Shibler struct proc *p;
8357307Shibler struct hpuxnetioctl_args *uap;
8443453Shibler int *retval;
8543453Shibler {
8641486Smckusick int *args, i;
8741486Smckusick register int code;
8843453Shibler int error;
8941486Smckusick
9041486Smckusick args = uap->args;
9141486Smckusick code = uap->call - MINBSDIPCCODE;
9243453Shibler if (code < 0 || code >= NUMBSDIPC || hpuxtobsdipc[code].rout == NULL)
9344421Skarels return (EINVAL);
9441486Smckusick if ((i = hpuxtobsdipc[code].nargs * sizeof (int)) &&
9543453Shibler (error = copyin((caddr_t)args, (caddr_t)uap, (u_int)i))) {
9641486Smckusick #ifdef KTRACE
9743453Shibler if (KTRPOINT(p, KTR_SYSCALL))
9843453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE,
9964477Shibler hpuxtobsdipc[code].nargs, (int *)uap);
10041486Smckusick #endif
10144421Skarels return (error);
10241486Smckusick }
10341486Smckusick #ifdef KTRACE
10443453Shibler if (KTRPOINT(p, KTR_SYSCALL))
10543453Shibler ktrsyscall(p->p_tracep, code + MINBSDIPCCODE,
10664477Shibler hpuxtobsdipc[code].nargs, (int *)uap);
10741486Smckusick #endif
10844421Skarels return ((*hpuxtobsdipc[code].rout)(p, uap, retval));
10941486Smckusick }
11041486Smckusick
socksetsize(size,m)11157307Shibler socksetsize(size, m)
11257307Shibler int size;
11357307Shibler struct mbuf *m;
11457307Shibler {
11557307Shibler register int tmp;
11657307Shibler
11757307Shibler if (size < sizeof(int)) {
11857307Shibler switch(size) {
11957307Shibler case 1:
12057307Shibler tmp = (int) *mtod(m, char *);
12157307Shibler break;
12257307Shibler case 2:
12357307Shibler tmp = (int) *mtod(m, short *);
12457307Shibler break;
12557307Shibler case 3:
12657307Shibler tmp = (((int) *mtod(m, int *)) >> 8) & 0xffffff;
12757307Shibler break;
12857307Shibler }
12957307Shibler *mtod(m, int *) = tmp;
13057307Shibler m->m_len = sizeof(int);
13157307Shibler } else {
13257307Shibler m->m_len = size;
13357307Shibler }
13457307Shibler }
13557307Shibler
13657307Shibler struct hpuxsetsockopt_args {
13757307Shibler int s;
13857307Shibler int level;
13957307Shibler int name;
14057307Shibler caddr_t val;
14157307Shibler int valsize;
14257307Shibler };
14357307Shibler /* ARGSUSED */
14443453Shibler hpuxsetsockopt(p, uap, retval)
14543453Shibler struct proc *p;
14657307Shibler struct hpuxsetsockopt_args *uap;
14743453Shibler int *retval;
14843453Shibler {
14941486Smckusick struct file *fp;
15041486Smckusick struct mbuf *m = NULL;
15143453Shibler int tmp, error;
15241486Smckusick
15346403Smckusick if (error = getsock(p->p_fd, uap->s, &fp))
15444421Skarels return (error);
15543453Shibler if (uap->valsize > MLEN)
15644421Skarels return (EINVAL);
15741486Smckusick if (uap->val) {
15841486Smckusick m = m_get(M_WAIT, MT_SOOPTS);
15943453Shibler if (m == NULL)
16044421Skarels return (ENOBUFS);
16143453Shibler if (error = copyin(uap->val, mtod(m, caddr_t),
16243453Shibler (u_int)uap->valsize)) {
16341486Smckusick (void) m_free(m);
16444421Skarels return (error);
16541486Smckusick }
16641486Smckusick if (uap->name == SO_LINGER) {
16741486Smckusick tmp = *mtod(m, int *);
16841486Smckusick mtod(m, struct linger *)->l_onoff = 1;
16941486Smckusick mtod(m, struct linger *)->l_linger = tmp;
17041486Smckusick m->m_len = sizeof(struct linger);
17141486Smckusick } else
17257307Shibler socksetsize(uap->valsize, m);
17341486Smckusick } else if (uap->name == ~SO_LINGER) {
17441486Smckusick m = m_get(M_WAIT, MT_SOOPTS);
17541486Smckusick if (m) {
17641486Smckusick uap->name = SO_LINGER;
17741486Smckusick mtod(m, struct linger *)->l_onoff = 0;
17841486Smckusick m->m_len = sizeof(struct linger);
17941486Smckusick }
18041486Smckusick }
18144421Skarels return (sosetopt((struct socket *)fp->f_data, uap->level,
18243453Shibler uap->name, m));
18341486Smckusick }
18441486Smckusick
18557307Shibler struct hpuxsetsockopt2_args {
18657307Shibler int s;
18757307Shibler int level;
18857307Shibler int name;
18957307Shibler caddr_t val;
19057307Shibler int valsize;
19157307Shibler };
19257307Shibler /* ARGSUSED */
19357307Shibler hpuxsetsockopt2(p, uap, retval)
19457307Shibler struct proc *p;
19557307Shibler register struct hpuxsetsockopt2_args *uap;
19657307Shibler int *retval;
19757307Shibler {
19857307Shibler struct file *fp;
19957307Shibler struct mbuf *m = NULL;
20057307Shibler int error;
20157307Shibler
20257307Shibler if (error = getsock(p->p_fd, uap->s, &fp))
20357307Shibler return (error);
20457307Shibler if (uap->valsize > MLEN)
20557307Shibler return (EINVAL);
20657307Shibler if (uap->val) {
20757307Shibler m = m_get(M_WAIT, MT_SOOPTS);
20857307Shibler if (m == NULL)
20957307Shibler return (ENOBUFS);
21057307Shibler if (error = copyin(uap->val, mtod(m, caddr_t),
21157307Shibler (u_int)uap->valsize)) {
21257307Shibler (void) m_free(m);
21357307Shibler return (error);
21457307Shibler }
21557307Shibler socksetsize(uap->valsize, m);
21657307Shibler }
21757307Shibler return (sosetopt((struct socket *)fp->f_data, uap->level,
21857307Shibler uap->name, m));
21957307Shibler }
22057307Shibler
22157307Shibler struct hpuxgetsockopt_args {
22257307Shibler int s;
22357307Shibler int level;
22457307Shibler int name;
22557307Shibler caddr_t val;
22657307Shibler int *avalsize;
22757307Shibler };
22843453Shibler hpuxgetsockopt(p, uap, retval)
22943453Shibler struct proc *p;
23057307Shibler struct hpuxgetsockopt_args *uap;
23143453Shibler int *retval;
23243453Shibler {
23341486Smckusick struct file *fp;
23441486Smckusick struct mbuf *m = NULL;
23543453Shibler int valsize, error;
23641486Smckusick
23746403Smckusick if (error = getsock(p->p_fd, uap->s, &fp))
23844421Skarels return (error);
23941486Smckusick if (uap->val) {
24043453Shibler if (error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
24143453Shibler sizeof (valsize)))
24244421Skarels return (error);
24341486Smckusick } else
24441486Smckusick valsize = 0;
24543453Shibler if (error = sogetopt((struct socket *)fp->f_data, uap->level,
24643453Shibler uap->name, &m))
24741486Smckusick goto bad;
24841486Smckusick if (uap->val && valsize && m != NULL) {
24941486Smckusick if (uap->name == SO_LINGER) {
25041486Smckusick if (mtod(m, struct linger *)->l_onoff)
25141486Smckusick *mtod(m, int *) = mtod(m, struct linger *)->l_linger;
25241486Smckusick else
25341486Smckusick *mtod(m, int *) = 0;
25441486Smckusick m->m_len = sizeof(int);
25541486Smckusick }
25641486Smckusick if (valsize > m->m_len)
25741486Smckusick valsize = m->m_len;
25843453Shibler error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
25943453Shibler if (error == 0)
26043453Shibler error = copyout((caddr_t)&valsize,
26143453Shibler (caddr_t)uap->avalsize, sizeof (valsize));
26241486Smckusick }
26341486Smckusick bad:
26441486Smckusick if (m != NULL)
26541486Smckusick (void) m_free(m);
26644421Skarels return (error);
26741486Smckusick }
26841486Smckusick #endif
269