📄 sys-solaris.c
字号:
* First split apart the device name and unit. */ slprintf(ifdev, sizeof(ifdev), "/dev/%s", name); for (q = ifdev + strlen(ifdev); --q >= ifdev; ) if (!isdigit(*q)) break; unit = atoi(q+1); q[1] = 0; /* * Open the device and do a DLPI attach and phys_addr_req. */ iffd = open(ifdev, O_RDWR); if (iffd < 0) { error("Can't open %s: %m", ifdev); return 0; } if (dlpi_attach(iffd, unit) < 0 || dlpi_get_reply(iffd, &reply.prim, DL_OK_ACK, sizeof(reply)) < 0 || dlpi_info_req(iffd) < 0 || dlpi_get_reply(iffd, &reply.prim, DL_INFO_ACK, sizeof(reply)) < 0) { close(iffd); return 0; } adrlen = reply.prim.info_ack.dl_addr_length; adrp = (unsigned char *)&reply + reply.prim.info_ack.dl_addr_offset;#if DL_CURRENT_VERSION >= 2 if (reply.prim.info_ack.dl_sap_length < 0) adrlen += reply.prim.info_ack.dl_sap_length; else adrp += reply.prim.info_ack.dl_sap_length;#endif hwaddr->sa_family = AF_UNSPEC; memcpy(hwaddr->sa_data, adrp, adrlen); return 1;}/* * get_hw_addr - obtain the hardware address for a named interface. */static intget_hw_addr(name, ina, hwaddr) char *name; u_int32_t ina; struct sockaddr *hwaddr;{ /* New way - get the address by doing an arp request. */ int s; struct arpreq req; s = socket(AF_INET, SOCK_DGRAM, 0); if (s < 0) return 0; memset(&req, 0, sizeof(req)); req.arp_pa.sa_family = AF_INET; INET_ADDR(req.arp_pa) = ina; if (ioctl(s, SIOCGARP, &req) < 0) { error("Couldn't get ARP entry for %s: %m", ip_ntoa(ina)); return 0; } *hwaddr = req.arp_ha; hwaddr->sa_family = AF_UNSPEC; return 1;}static intdlpi_attach(fd, ppa) int fd, ppa;{ dl_attach_req_t req; struct strbuf buf; req.dl_primitive = DL_ATTACH_REQ; req.dl_ppa = ppa; buf.len = sizeof(req); buf.buf = (void *) &req; return putmsg(fd, &buf, NULL, RS_HIPRI);}static intdlpi_info_req(fd) int fd;{ dl_info_req_t req; struct strbuf buf; req.dl_primitive = DL_INFO_REQ; buf.len = sizeof(req); buf.buf = (void *) &req; return putmsg(fd, &buf, NULL, RS_HIPRI);}static intdlpi_get_reply(fd, reply, expected_prim, maxlen) union DL_primitives *reply; int fd, expected_prim, maxlen;{ struct strbuf buf; int flags, n; struct pollfd pfd; /* * Use poll to wait for a message with a timeout. */ pfd.fd = fd; pfd.events = POLLIN | POLLPRI; do { n = poll(&pfd, 1, 1000); } while (n == -1 && errno == EINTR); if (n <= 0) return -1; /* * Get the reply. */ buf.maxlen = maxlen; buf.buf = (void *) reply; flags = 0; if (getmsg(fd, &buf, NULL, &flags) < 0) return -1; if (buf.len < sizeof(ulong)) { if (debug) dbglog("dlpi response short (len=%d)\n", buf.len); return -1; } if (reply->dl_primitive == expected_prim) return 0; if (debug) { if (reply->dl_primitive == DL_ERROR_ACK) { dbglog("dlpi error %d (unix errno %d) for prim %x\n", reply->error_ack.dl_errno, reply->error_ack.dl_unix_errno, reply->error_ack.dl_error_primitive); } else { dbglog("dlpi unexpected response prim %x\n", reply->dl_primitive); } } return -1;}/* * Return user specified netmask, modified by any mask we might determine * for address `addr' (in network byte order). * Here we scan through the system's list of interfaces, looking for * any non-point-to-point interfaces which might appear to be on the same * network as `addr'. If we find any, we OR in their netmask to the * user-specified netmask. */u_int32_tGetMask(addr) u_int32_t addr;{ u_int32_t mask, nmask, ina; struct ifreq *ifr, *ifend, ifreq; int nif; struct ifconf ifc; addr = ntohl(addr); if (IN_CLASSA(addr)) /* determine network mask for address class */ nmask = IN_CLASSA_NET; else if (IN_CLASSB(addr)) nmask = IN_CLASSB_NET; else nmask = IN_CLASSC_NET; /* class D nets are disallowed by bad_ip_adrs */ mask = netmask | htonl(nmask); /* * Scan through the system's network interfaces. */#ifdef SIOCGIFNUM if (ioctl(ipfd, SIOCGIFNUM, &nif) < 0)#endif nif = MAX_IFS; ifc.ifc_len = nif * sizeof(struct ifreq); ifc.ifc_buf = (caddr_t) malloc(ifc.ifc_len); if (ifc.ifc_buf == 0) return mask; if (ioctl(ipfd, SIOCGIFCONF, &ifc) < 0) { warn("Couldn't get system interface list: %m"); free(ifc.ifc_buf); return mask; } ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); for (ifr = ifc.ifc_req; ifr < ifend; ++ifr) { /* * Check the interface's internet address. */ if (ifr->ifr_addr.sa_family != AF_INET) continue; ina = INET_ADDR(ifr->ifr_addr); if ((ntohl(ina) & nmask) != (addr & nmask)) continue; /* * Check that the interface is up, and not point-to-point or loopback. */ strlcpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); if (ioctl(ipfd, SIOCGIFFLAGS, &ifreq) < 0) continue; if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) != IFF_UP) continue; /* * Get its netmask and OR it into our mask. */ if (ioctl(ipfd, SIOCGIFNETMASK, &ifreq) < 0) continue; mask |= INET_ADDR(ifreq.ifr_addr); } free(ifc.ifc_buf); return mask;}/* * logwtmp - write an accounting record to the /var/adm/wtmp file. */voidlogwtmp(line, name, host) const char *line, *name, *host;{ static struct utmpx utmpx; if (name[0] != 0) { /* logging in */ strncpy(utmpx.ut_user, name, sizeof(utmpx.ut_user)); strncpy(utmpx.ut_id, ifname, sizeof(utmpx.ut_id)); strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line)); utmpx.ut_pid = getpid(); utmpx.ut_type = USER_PROCESS; } else { utmpx.ut_type = DEAD_PROCESS; } gettimeofday(&utmpx.ut_tv, NULL); updwtmpx("/var/adm/wtmpx", &utmpx);}/* * get_host_seed - return the serial number of this machine. */intget_host_seed(){ char buf[32]; if (sysinfo(SI_HW_SERIAL, buf, sizeof(buf)) < 0) { error("sysinfo: %m"); return 0; } return (int) strtoul(buf, NULL, 16);}static intstrioctl(fd, cmd, ptr, ilen, olen) int fd, cmd, ilen, olen; void *ptr;{ struct strioctl str; str.ic_cmd = cmd; str.ic_timout = 0; str.ic_len = ilen; str.ic_dp = ptr; if (ioctl(fd, I_STR, &str) == -1) return -1; if (str.ic_len != olen) dbglog("strioctl: expected %d bytes, got %d for cmd %x\n", olen, str.ic_len, cmd); return 0;}#if 0/* * lock - create a lock file for the named lock device */#define LOCK_PREFIX "/var/spool/locks/LK."static char lock_file[40]; /* name of lock file created */intlock(dev) char *dev;{ int n, fd, pid; struct stat sbuf; char ascii_pid[12]; if (stat(dev, &sbuf) < 0) { error("Can't get device number for %s: %m", dev); return -1; } if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { error("Can't lock %s: not a character device", dev); return -1; } slprintf(lock_file, sizeof(lock_file), "%s%03d.%03d.%03d", LOCK_PREFIX, major(sbuf.st_dev), major(sbuf.st_rdev), minor(sbuf.st_rdev)); while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { if (errno == EEXIST && (fd = open(lock_file, O_RDONLY, 0)) >= 0) { /* Read the lock file to find out who has the device locked */ n = read(fd, ascii_pid, 11); if (n <= 0) { error("Can't read pid from lock file %s", lock_file); close(fd); } else { ascii_pid[n] = 0; pid = atoi(ascii_pid); if (pid > 0 && kill(pid, 0) == -1 && errno == ESRCH) { /* pid no longer exists - remove the lock file */ if (unlink(lock_file) == 0) { close(fd); notice("Removed stale lock on %s (pid %d)", dev, pid); continue; } else warn("Couldn't remove stale lock on %s", dev); } else notice("Device %s is locked by pid %d", dev, pid); } close(fd); } else error("Can't create lock file %s: %m", lock_file); lock_file[0] = 0; return -1; } slprintf(ascii_pid, sizeof(ascii_pid), "%10d\n", getpid()); write(fd, ascii_pid, 11); close(fd); return 1;}/* * unlock - remove our lockfile */voidunlock(){ if (lock_file[0]) { unlink(lock_file); lock_file[0] = 0; }}#endif/* * cifroute - delete a route through the addresses given. */intcifroute(u, our, his) int u; u_int32_t our, his;{ struct rtentry rt; memset(&rt, 0, sizeof(rt)); rt.rt_dst.sa_family = AF_INET; INET_ADDR(rt.rt_dst) = his; rt.rt_gateway.sa_family = AF_INET; INET_ADDR(rt.rt_gateway) = our; rt.rt_flags = RTF_HOST; if (ioctl(ipfd, SIOCDELRT, &rt) < 0) { error("Can't delete route: %m"); return 0; } return 1;}/* * have_route_to - determine if the system has a route to the specified * IP address. Returns 0 if not, 1 if so, -1 if we can't tell. * `addr' is in network byte order. * For demand mode to work properly, we have to ignore routes * through our own interface. */#ifndef T_CURRENT /* needed for Solaris 2.5 */#define T_CURRENT MI_T_CURRENT#endifinthave_route_to(addr) u_int32_t addr;{#ifdef SOL2 int fd, r, flags, i; struct { struct T_optmgmt_req req; struct opthdr hdr; } req; union { struct T_optmgmt_ack ack; unsigned char space[64]; } ack; struct opthdr *rh; struct strbuf cbuf, dbuf; int nroutes; mib2_ipRouteEntry_t routes[8]; mib2_ipRouteEntry_t *rp; fd = open(mux_dev_name, O_RDWR); if (fd < 0) { warn("have_route_to: couldn't open %s: %m", mux_dev_name); return -1; } req.req.PRIM_type = T_OPTMGMT_REQ; req.req.OPT_offset = (char *) &req.hdr - (char *) &req; req.req.OPT_length = sizeof(req.hdr); req.req.MGMT_flags = T_CURRENT; req.hdr.level = MIB2_IP; req.hdr.name = 0; req.hdr.len = 0; cbuf.buf = (char *) &req; cbuf.len = sizeof(req); if (putmsg(fd, &cbuf, NULL, 0) == -1) { warn("have_route_to: putmsg: %m"); close(fd); return -1; } for (;;) { cbuf.buf = (char *) &ack; cbuf.maxlen = sizeof(ack); dbuf.buf = (char *) routes; dbuf.maxlen = sizeof(routes); flags = 0; r = getmsg(fd, &cbuf, &dbuf, &flags); if (r == -1) { warn("have_route_to: getmsg: %m"); close(fd); return -1; } if (cbuf.len < sizeof(struct T_optmgmt_ack) || ack.ack.PRIM_type != T_OPTMGMT_ACK || ack.ack.MGMT_flags != T_SUCCESS || ack.ack.OPT_length < sizeof(struct opthdr)) { dbglog("have_route_to: bad message len=%d prim=%d", cbuf.len, ack.ack.PRIM_type); close(fd); return -1; } rh = (struct opthdr *) ((char *)&ack + ack.ack.OPT_offset); if (rh->level == 0 && rh->name == 0) break; if (rh->level != MIB2_IP || rh->name != MIB2_IP_21) { while (r == MOREDATA) r = getmsg(fd, NULL, &dbuf, &flags); continue; } for (;;) { nroutes = dbuf.len / sizeof(mib2_ipRouteEntry_t); for (rp = routes, i = 0; i < nroutes; ++i, ++rp) { if (rp->ipRouteMask != ~0) { dbglog("have_route_to: dest=%x gw=%x mask=%x\n", rp->ipRouteDest, rp->ipRouteNextHop, rp->ipRouteMask); if (((addr ^ rp->ipRouteDest) & rp->ipRouteMask) == 0 && rp->ipRouteNextHop != remote_addr) return 1; } } if (r == 0) break; r = getmsg(fd, NULL, &dbuf, &flags); } } close(fd); return 0;#else return -1;#endif /* SOL2 */}/* * get_pty - get a pty master/slave pair and chown the slave side to * the uid given. Assumes slave_name points to MAXPATHLEN bytes of space. */intget_pty(master_fdp, slave_fdp, slave_name, uid) int *master_fdp; int *slave_fdp; char *slave_name; int uid;{ int mfd, sfd; char *pty_name; struct termios tios; mfd = open("/dev/ptmx", O_RDWR); if (mfd < 0) { error("Couldn't open pty master: %m"); return 0; } pty_name = ptsname(mfd); if (pty_name == NULL) { error("Couldn't get name of pty slave"); close(mfd); return 0; } if (chown(pty_name, uid, -1) < 0) warn("Couldn't change owner of pty slave: %m"); if (chmod(pty_name, S_IRUSR | S_IWUSR) < 0) warn("Couldn't change permissions on pty slave: %m"); if (unlockpt(mfd) < 0) warn("Couldn't unlock pty slave: %m"); sfd = open(pty_name, O_RDWR); if (sfd < 0) { error("Couldn't open pty slave %s: %m", pty_name); close(mfd); return 0; } if (ioctl(sfd, I_PUSH, "ptem") < 0) warn("Couldn't push ptem module on pty slave: %m"); dbglog("Using %s", pty_name); strlcpy(slave_name, pty_name, MAXPATHLEN); *master_fdp = mfd; *slave_fdp = sfd; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -