From b7080c8e96625177072137d504eb8e9c9d748e49 Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 10 Apr 2001 09:43:13 +0000 Subject: [PATCH] network_cmds-76.tar.gz --- Makefile | 59 + Makefile.include | 12 + Makefile.preamble | 1 + PB.project | 82 + alias/Makefile | 59 + alias/Makefile.postamble | 100 + alias/Makefile.preamble | 138 + alias/PB.project | 39 + alias/alias.c | 1318 ++++++++ alias/alias.h | 166 + alias/alias_cuseeme.c | 120 + alias/alias_db.c | 2330 +++++++++++++ alias/alias_ftp.c | 229 ++ alias/alias_irc.c | 316 ++ alias/alias_local.h | 170 + alias/alias_nbt.c | 711 ++++ alias/alias_proxy.c | 805 +++++ alias/alias_util.c | 137 + arp.tproj/Makefile | 48 + arp.tproj/Makefile.postamble | 115 + arp.tproj/Makefile.preamble | 113 + arp.tproj/PB.project | 41 + arp.tproj/arp.8 | 122 + arp.tproj/arp.c | 554 +++ arp.tproj/arp4.4 | 124 + bootparams/Makefile | 46 + bootparams/Makefile.postamble | 100 + bootparams/Makefile.preamble | 138 + bootparams/PB.project | 22 + bootparams/bootparamd.tproj/Makefile | 48 + .../bootparamd.tproj/Makefile.postamble | 100 + bootparams/bootparamd.tproj/Makefile.preamble | 140 + bootparams/bootparamd.tproj/PB.project | 27 + bootparams/bootparamd.tproj/bootparam_proc.c | 210 ++ bootparams/bootparamd.tproj/bootparamd.c | 147 + bootparams/bootparams/Makefile | 52 + bootparams/bootparams/Makefile.postamble | 109 + bootparams/bootparams/Makefile.preamble | 144 + bootparams/bootparams/PB.project | 30 + bootparams/bootparams/bootparam_prot.x | 119 + bootparams/bpwhoami.tproj/Makefile | 48 + bootparams/bpwhoami.tproj/Makefile.postamble | 100 + bootparams/bpwhoami.tproj/Makefile.preamble | 139 + bootparams/bpwhoami.tproj/PB.project | 27 + bootparams/bpwhoami.tproj/bpwhoami.c | 246 ++ domainname.tproj/Makefile | 48 + domainname.tproj/Makefile.dist | 6 + domainname.tproj/PB.project | 36 + domainname.tproj/domainname.1 | 60 + domainname.tproj/domainname.c | 97 + ftp.tproj/Makefile | 52 + ftp.tproj/Makefile.postamble | 123 + ftp.tproj/Makefile.preamble | 130 + ftp.tproj/PB.project | 34 + ftp.tproj/cmds.c | 2236 ++++++++++++ ftp.tproj/cmdtab.c | 207 ++ ftp.tproj/domacro.c | 168 + ftp.tproj/extern.h | 176 + ftp.tproj/ftp.1 | 1157 +++++++ ftp.tproj/ftp.c | 1542 +++++++++ ftp.tproj/ftp_var.c | 135 + ftp.tproj/ftp_var.h | 149 + ftp.tproj/h.template | 11 + ftp.tproj/m.template | 18 + ftp.tproj/main.c | 528 +++ ftp.tproj/pathnames.h | 62 + ftp.tproj/ruserpass.c | 300 ++ ftpd.tproj/Makefile | 53 + ftpd.tproj/Makefile.postamble | 111 + ftpd.tproj/Makefile.preamble | 119 + ftpd.tproj/PB.project | 40 + ftpd.tproj/extern.h | 88 + ftpd.tproj/ftpcmd.y | 1269 +++++++ ftpd.tproj/ftpd.8 | 291 ++ ftpd.tproj/ftpd.c | 1686 ++++++++++ ftpd.tproj/logwtmp.c | 98 + ftpd.tproj/pathnames.h | 63 + ftpd.tproj/popen.c | 194 ++ ftpd.tproj/vers.c | 62 + identd.tproj/CREDITS | 52 + identd.tproj/Makefile | 50 + identd.tproj/Makefile.dist | 10 + identd.tproj/Makefile.preamble | 2 + identd.tproj/PB.project | 40 + identd.tproj/README | 129 + identd.tproj/config.c | 71 + identd.tproj/error.h | 67 + identd.tproj/identd.8 | 238 ++ identd.tproj/identd.c | 643 ++++ identd.tproj/identd.h | 68 + identd.tproj/netbsd.c | 265 ++ identd.tproj/parse.c | 425 +++ identd.tproj/proxy.c | 123 + identd.tproj/version.c | 25 + identd.tproj/xpaths.h | 89 + ifconfig.tproj/Makefile | 51 + ifconfig.tproj/Makefile.dist | 6 + ifconfig.tproj/Makefile.postamble | 3 + ifconfig.tproj/Makefile.preamble | 3 + ifconfig.tproj/PB.project | 32 + ifconfig.tproj/ifconfig.8 | 320 ++ ifconfig.tproj/ifconfig.c | 870 +++++ ifconfig.tproj/ifconfig.h | 46 + ifconfig.tproj/ifmedia.c | 554 +++ inetd.tproj/Makefile | 50 + inetd.tproj/Makefile.postamble | 110 + inetd.tproj/Makefile.preamble | 113 + inetd.tproj/PB.project | 41 + inetd.tproj/inetd.8 | 381 +++ inetd.tproj/inetd.c | 1293 +++++++ inetd.tproj/pathnames.h | 67 + ipfw.tproj/Makefile | 48 + ipfw.tproj/Makefile.postamble | 104 + ipfw.tproj/Makefile.preamble | 140 + ipfw.tproj/PB.project | 25 + ipfw.tproj/ipfw.8 | 733 ++++ ipfw.tproj/ipfw.c | 1613 +++++++++ logger.tproj/Makefile | 49 + logger.tproj/Makefile.postamble | 123 + logger.tproj/Makefile.preamble | 130 + logger.tproj/PB.project | 34 + logger.tproj/h.template | 11 + logger.tproj/logger.1 | 102 + logger.tproj/logger.c | 205 ++ logger.tproj/m.template | 18 + makedbm.tproj/Makefile | 48 + makedbm.tproj/Makefile.postamble | 101 + makedbm.tproj/Makefile.preamble | 123 + makedbm.tproj/PB.project | 27 + makedbm.tproj/db.c | 98 + makedbm.tproj/db.h | 66 + makedbm.tproj/makedbm.8 | 97 + makedbm.tproj/makedbm.c | 444 +++ makedbm.tproj/ypdb.c | 297 ++ makedbm.tproj/ypdb.h | 100 + makedbm.tproj/ypdef.h | 94 + natd.tproj/Makefile | 50 + natd.tproj/Makefile.postamble | 104 + natd.tproj/Makefile.preamble | 140 + natd.tproj/PB.project | 27 + natd.tproj/icmp.c | 126 + natd.tproj/natd.8 | 426 +++ natd.tproj/natd.c | 1578 +++++++++ natd.tproj/natd.h | 24 + netstat.tproj/DERIVED_FILES | 1 + netstat.tproj/Makefile | 54 + netstat.tproj/Makefile.postamble | 2 + netstat.tproj/Makefile.preamble | 4 + netstat.tproj/PB.project | 49 + netstat.tproj/data.c | 28 + netstat.tproj/if.c | 511 +++ netstat.tproj/inet.c | 616 ++++ netstat.tproj/iso.c | 866 +++++ netstat.tproj/main.c | 667 ++++ netstat.tproj/mbuf.c | 155 + netstat.tproj/mroute.c | 210 ++ netstat.tproj/netstat.1 | 289 ++ netstat.tproj/netstat.h | 149 + netstat.tproj/route.c | 918 +++++ netstat.tproj/tp_astring.c | 74 + netstat.tproj/unix.c | 184 + newclient.tproj/Makefile | 36 + newclient.tproj/Makefile.preamble | 1 + newclient.tproj/PB.project | 34 + newclient.tproj/newclient.csh | 233 ++ nfsd.tproj/Makefile | 51 + nfsd.tproj/Makefile.dist | 9 + nfsd.tproj/Makefile.preamble | 2 + nfsd.tproj/PB.project | 32 + nfsd.tproj/nfsd.8 | 115 + nfsd.tproj/nfsd.c | 657 ++++ nfsiod.tproj/Makefile | 51 + nfsiod.tproj/Makefile.dist | 7 + nfsiod.tproj/Makefile.preamble | 2 + nfsiod.tproj/PB.project | 32 + nfsiod.tproj/nfsiod.8 | 74 + nfsiod.tproj/nfsiod.c | 184 + nfsstat.tproj/Makefile | 51 + nfsstat.tproj/Makefile.postamble | 2 + nfsstat.tproj/Makefile.preamble | 3 + nfsstat.tproj/PB.project | 31 + nfsstat.tproj/nfsstat.1 | 88 + nfsstat.tproj/nfsstat.c | 445 +++ pcap/Makefile | 63 + pcap/Makefile.postamble | 122 + pcap/Makefile.preamble | 130 + pcap/PB.project | 48 + pcap/bpf_filter.c | 546 +++ pcap/bpf_image.c | 315 ++ pcap/etherent.c | 182 + pcap/ethertype.h | 100 + pcap/gencode.c | 1843 ++++++++++ pcap/gencode.h | 196 ++ pcap/grammar.y | 280 ++ pcap/inet.c | 249 ++ pcap/nametoaddr.c | 394 +++ pcap/optimize.c | 2029 +++++++++++ pcap/pcap-bpf.c | 273 ++ pcap/pcap-int.h | 129 + pcap/pcap-namedb.h | 101 + pcap/pcap.c | 219 ++ pcap/pcap.h | 166 + pcap/savefile.c | 362 ++ pcap/scanner.l | 198 ++ ping.tproj/Makefile | 51 + ping.tproj/Makefile.dist | 8 + ping.tproj/Makefile.postamble | 1 + ping.tproj/Makefile.preamble | 2 + ping.tproj/PB.project | 31 + ping.tproj/ping.8 | 328 ++ ping.tproj/ping.c | 1018 ++++++ portmap.tproj/Makefile | 48 + portmap.tproj/Makefile.postamble | 110 + portmap.tproj/Makefile.preamble | 113 + portmap.tproj/PB.project | 41 + portmap.tproj/portmap.8 | 110 + portmap.tproj/portmap.c | 661 ++++ rarpd.tproj/Makefile | 52 + rarpd.tproj/Makefile.dist | 10 + rarpd.tproj/Makefile.preamble | 2 + rarpd.tproj/PB.project | 37 + rarpd.tproj/rarpd.8 | 92 + rarpd.tproj/rarpd.c | 831 +++++ rbootd.tproj/Makefile | 50 + rbootd.tproj/Makefile.postamble | 111 + rbootd.tproj/Makefile.preamble | 119 + rbootd.tproj/PB.project | 39 + rbootd.tproj/bpf.c | 445 +++ rbootd.tproj/conf.c | 113 + rbootd.tproj/defs.h | 208 ++ rbootd.tproj/parseconf.c | 382 +++ rbootd.tproj/pathnames.h | 74 + rbootd.tproj/rbootd.8 | 156 + rbootd.tproj/rbootd.c | 531 +++ rbootd.tproj/rmp.h | 118 + rbootd.tproj/rmp_var.h | 267 ++ rbootd.tproj/rmpproto.c | 616 ++++ rbootd.tproj/utils.c | 580 ++++ rcp.tproj/Makefile | 51 + rcp.tproj/Makefile.dist | 13 + rcp.tproj/Makefile.postamble | 5 + rcp.tproj/Makefile.preamble | 5 + rcp.tproj/PB.project | 29 + rcp.tproj/extern.h | 73 + rcp.tproj/pathnames.h | 62 + rcp.tproj/rcp.1 | 159 + rcp.tproj/rcp.c | 938 ++++++ rcp.tproj/util.c | 187 ++ revnetgroup.tproj/Makefile | 48 + revnetgroup.tproj/Makefile.postamble | 101 + revnetgroup.tproj/Makefile.preamble | 123 + revnetgroup.tproj/PB.project | 27 + revnetgroup.tproj/hash.c | 244 ++ revnetgroup.tproj/hash.h | 91 + revnetgroup.tproj/parse_netgroup.c | 394 +++ revnetgroup.tproj/revnetgroup.8 | 138 + revnetgroup.tproj/revnetgroup.c | 221 ++ rexecd.tproj/Makefile | 48 + rexecd.tproj/Makefile.postamble | 111 + rexecd.tproj/Makefile.preamble | 119 + rexecd.tproj/PB.project | 42 + rexecd.tproj/rexecd.8 | 149 + rexecd.tproj/rexecd.c | 285 ++ rlogin.tproj/Makefile | 55 + rlogin.tproj/Makefile.postamble | 1 + rlogin.tproj/Makefile.preamble | 3 + rlogin.tproj/PB.project | 42 + rlogin.tproj/des_rw.c | 226 ++ rlogin.tproj/kcmd.c | 329 ++ rlogin.tproj/krb.h | 74 + rlogin.tproj/krcmd.c | 178 + rlogin.tproj/rlogin.1 | 188 ++ rlogin.tproj/rlogin.c | 1011 ++++++ rlogind.tproj/Makefile | 55 + rlogind.tproj/Makefile.postamble | 2 + rlogind.tproj/Makefile.preamble | 3 + rlogind.tproj/PB.project | 41 + rlogind.tproj/pathnames.h | 61 + rlogind.tproj/rlogind.8 | 168 + rlogind.tproj/rlogind.c | 783 +++++ route.tproj/Makefile | 53 + route.tproj/Makefile.dist | 25 + route.tproj/Makefile.postamble | 1 + route.tproj/Makefile.preamble | 2 + route.tproj/PB.project | 43 + route.tproj/ccitt_addr.c | 199 ++ route.tproj/keywords.h | 109 + route.tproj/route.8 | 325 ++ route.tproj/route.c | 1523 +++++++++ routed.tproj/Makefile | 51 + routed.tproj/Makefile.dist | 22 + routed.tproj/Makefile.preamble | 2 + routed.tproj/PB.project | 53 + routed.tproj/af.c | 193 ++ routed.tproj/af.h | 88 + routed.tproj/defs.c | 26 + routed.tproj/defs.h | 131 + routed.tproj/if.c | 170 + routed.tproj/inet.c | 267 ++ routed.tproj/input.c | 383 +++ routed.tproj/interface.h | 113 + routed.tproj/main.c | 367 ++ routed.tproj/output.c | 194 ++ routed.tproj/pathnames.h | 61 + routed.tproj/routed.8 | 358 ++ routed.tproj/startup.c | 537 +++ routed.tproj/table.h | 131 + routed.tproj/tables.c | 450 +++ routed.tproj/timer.c | 149 + routed.tproj/trace.c | 448 +++ routed.tproj/trace.h | 119 + rpc_yppasswdd.tproj/Makefile | 49 + rpc_yppasswdd.tproj/Makefile.postamble | 101 + rpc_yppasswdd.tproj/Makefile.preamble | 123 + rpc_yppasswdd.tproj/PB.project | 27 + rpc_yppasswdd.tproj/passwd.c | 461 +++ rpc_yppasswdd.tproj/rpc.yppasswdd.8 | 97 + rpc_yppasswdd.tproj/rpc.yppasswdd.c | 208 ++ rpc_yppasswdd.tproj/yppasswd.h | 113 + rpc_yppasswdd.tproj/yppasswdd_mkpw.c | 321 ++ rpc_yppasswdd.tproj/yppasswdd_proc.c | 89 + rpcinfo.tproj/Makefile | 49 + rpcinfo.tproj/Makefile.postamble | 111 + rpcinfo.tproj/Makefile.preamble | 119 + rpcinfo.tproj/PB.project | 45 + rpcinfo.tproj/h.template | 9 + rpcinfo.tproj/m.template | 18 + rpcinfo.tproj/rpcinfo.c | 690 ++++ rsh.tproj/Makefile | 50 + rsh.tproj/Makefile.postamble | 5 + rsh.tproj/Makefile.preamble | 4 + rsh.tproj/PB.project | 30 + rsh.tproj/pathnames.h | 59 + rsh.tproj/rsh.1 | 187 ++ rsh.tproj/rsh.c | 504 +++ rshd.tproj/Makefile | 48 + rshd.tproj/Makefile.postamble | 113 + rshd.tproj/Makefile.preamble | 119 + rshd.tproj/PB.project | 42 + rshd.tproj/rshd.8 | 209 ++ rshd.tproj/rshd.c | 809 +++++ ruptime.tproj/Makefile | 49 + ruptime.tproj/Makefile.dist | 5 + ruptime.tproj/Makefile.postamble | 123 + ruptime.tproj/Makefile.preamble | 130 + ruptime.tproj/PB.project | 35 + ruptime.tproj/h.template | 11 + ruptime.tproj/m.template | 18 + ruptime.tproj/ruptime.1 | 81 + ruptime.tproj/ruptime.c | 301 ++ rwho.tproj/Makefile | 49 + rwho.tproj/Makefile.dist | 5 + rwho.tproj/Makefile.postamble | 123 + rwho.tproj/Makefile.preamble | 130 + rwho.tproj/PB.project | 27 + rwho.tproj/rwho.1 | 80 + rwho.tproj/rwho.c | 204 ++ rwhod.tproj/Makefile | 48 + rwhod.tproj/Makefile.postamble | 110 + rwhod.tproj/Makefile.preamble | 113 + rwhod.tproj/PB.project | 41 + rwhod.tproj/rwhod.8 | 146 + rwhod.tproj/rwhod.c | 562 ++++ slattach.tproj/Makefile | 48 + slattach.tproj/Makefile.dist | 7 + slattach.tproj/Makefile.preamble | 2 + slattach.tproj/PB.project | 32 + slattach.tproj/slattach.8 | 90 + slattach.tproj/slattach.c | 188 ++ sliplogin.tproj/Makefile | 51 + sliplogin.tproj/Makefile.postamble | 110 + sliplogin.tproj/Makefile.preamble | 113 + sliplogin.tproj/PB.project | 48 + sliplogin.tproj/pathnames.h | 69 + sliplogin.tproj/slip.hosts | 11 + sliplogin.tproj/slip.login | 12 + sliplogin.tproj/sliplogin.8 | 220 ++ sliplogin.tproj/sliplogin.c | 404 +++ spray.tproj/Makefile | 49 + spray.tproj/Makefile.dist | 7 + spray.tproj/Makefile.postamble | 126 + spray.tproj/Makefile.preamble | 4 + spray.tproj/PB.project | 37 + spray.tproj/spray.c | 247 ++ spray.tproj/spray.x | 24 + startslip.tproj/Makefile | 48 + startslip.tproj/Makefile.dist | 6 + startslip.tproj/Makefile.preamble | 2 + startslip.tproj/PB.project | 32 + startslip.tproj/startslip.1 | 105 + startslip.tproj/startslip.c | 466 +++ stdethers.tproj/Makefile | 46 + stdethers.tproj/Makefile.postamble | 101 + stdethers.tproj/Makefile.preamble | 123 + stdethers.tproj/PB.project | 27 + stdethers.tproj/stdethers.8 | 55 + stdethers.tproj/stdethers.c | 220 ++ stdhosts.tproj/Makefile | 46 + stdhosts.tproj/Makefile.postamble | 101 + stdhosts.tproj/Makefile.preamble | 123 + stdhosts.tproj/PB.project | 26 + stdhosts.tproj/stdhosts.8 | 55 + stdhosts.tproj/stdhosts.c | 172 + syslogd.tproj/Makefile | 51 + syslogd.tproj/Makefile.postamble | 111 + syslogd.tproj/Makefile.preamble | 115 + syslogd.tproj/PB.project | 41 + syslogd.tproj/pathnames.h | 63 + syslogd.tproj/syslog.conf.5 | 224 ++ syslogd.tproj/syslogd.8 | 122 + syslogd.tproj/syslogd.c | 1162 +++++++ talk.tproj/Makefile | 51 + talk.tproj/Makefile.preamble | 3 + talk.tproj/PB.project | 37 + talk.tproj/ctl.c | 133 + talk.tproj/ctl_transact.c | 133 + talk.tproj/display.c | 210 ++ talk.tproj/get_addrs.c | 103 + talk.tproj/get_names.c | 138 + talk.tproj/init_disp.c | 169 + talk.tproj/invite.c | 208 ++ talk.tproj/io.c | 162 + talk.tproj/look_up.c | 135 + talk.tproj/msgs.c | 98 + talk.tproj/talk.1 | 129 + talk.tproj/talk.c | 94 + talk.tproj/talk.h | 81 + talk.tproj/talk_ctl.h | 66 + talkd.tproj/Makefile | 51 + talkd.tproj/Makefile.dist | 8 + talkd.tproj/Makefile.postamble | 113 + talkd.tproj/Makefile.preamble | 120 + talkd.tproj/PB.project | 39 + talkd.tproj/announce.c | 191 ++ talkd.tproj/print.c | 111 + talkd.tproj/process.c | 246 ++ talkd.tproj/table.c | 263 ++ talkd.tproj/talkd.8 | 75 + talkd.tproj/talkd.c | 153 + talkd.tproj/talkd.h | 32 + tcpdump.tproj/Makefile | 63 + tcpdump.tproj/Makefile.postamble | 123 + tcpdump.tproj/Makefile.preamble | 130 + tcpdump.tproj/PB.project | 98 + tcpdump.tproj/addrtoname.c | 779 +++++ tcpdump.tproj/addrtoname.h | 59 + tcpdump.tproj/appletalk.h | 190 ++ tcpdump.tproj/bootp.h | 132 + tcpdump.tproj/bpf_dump.c | 88 + tcpdump.tproj/decnet.h | 476 +++ tcpdump.tproj/ethertype.h | 99 + tcpdump.tproj/extract.h | 80 + tcpdump.tproj/fddi.h | 92 + tcpdump.tproj/gnuc.h | 66 + tcpdump.tproj/igrp.h | 59 + tcpdump.tproj/interface.h | 230 ++ tcpdump.tproj/ipx.h | 52 + tcpdump.tproj/llc.h | 143 + tcpdump.tproj/machdep.c | 72 + tcpdump.tproj/machdep.h | 50 + tcpdump.tproj/mib.h | 1279 +++++++ tcpdump.tproj/netbios.h | 39 + tcpdump.tproj/nfs.h | 470 +++ tcpdump.tproj/nfsfh.h | 57 + tcpdump.tproj/nfsv2.h | 285 ++ tcpdump.tproj/ntp.h | 140 + tcpdump.tproj/os-solaris2.h | 77 + tcpdump.tproj/os-sunos4.h | 238 ++ tcpdump.tproj/os-ultrix4.h | 62 + tcpdump.tproj/ospf.h | 246 ++ tcpdump.tproj/parsenfsfh.c | 443 +++ tcpdump.tproj/print-arp.c | 153 + tcpdump.tproj/print-atalk.c | 595 ++++ tcpdump.tproj/print-atm.c | 171 + tcpdump.tproj/print-bootp.c | 371 ++ tcpdump.tproj/print-decnet.c | 798 +++++ tcpdump.tproj/print-domain.c | 423 +++ tcpdump.tproj/print-dvmrp.c | 383 +++ tcpdump.tproj/print-egp.c | 377 +++ tcpdump.tproj/print-ether.c | 219 ++ tcpdump.tproj/print-fddi.c | 377 +++ tcpdump.tproj/print-gre.c | 164 + tcpdump.tproj/print-icmp.c | 377 +++ tcpdump.tproj/print-igrp.c | 161 + tcpdump.tproj/print-ip.c | 547 +++ tcpdump.tproj/print-ipx.c | 238 ++ tcpdump.tproj/print-isoclns.c | 340 ++ tcpdump.tproj/print-krb.c | 317 ++ tcpdump.tproj/print-llc.c | 216 ++ tcpdump.tproj/print-netbios.c | 122 + tcpdump.tproj/print-nfs.c | 891 +++++ tcpdump.tproj/print-ntp.c | 307 ++ tcpdump.tproj/print-null.c | 142 + tcpdump.tproj/print-ospf.c | 603 ++++ tcpdump.tproj/print-pim.c | 123 + tcpdump.tproj/print-ppp.c | 128 + tcpdump.tproj/print-rip.c | 182 + tcpdump.tproj/print-skip.c | 943 ++++++ tcpdump.tproj/print-sl.c | 280 ++ tcpdump.tproj/print-snmp.c | 1063 ++++++ tcpdump.tproj/print-sunrpc.c | 155 + tcpdump.tproj/print-tcp.c | 383 +++ tcpdump.tproj/print-tftp.c | 162 + tcpdump.tproj/print-udp.c | 464 +++ tcpdump.tproj/print-wb.c | 456 +++ tcpdump.tproj/strcasecmp.c | 112 + tcpdump.tproj/tcpdump.c | 451 +++ tcpdump.tproj/util.c | 352 ++ tcpdump.tproj/version.c | 27 + tcpdump.tproj/vfprintf.c | 85 + telnet.tproj/Makefile | 57 + telnet.tproj/Makefile.dist | 73 + telnet.tproj/Makefile.preamble | 4 + telnet.tproj/PB.project | 47 + telnet.tproj/README | 743 ++++ telnet.tproj/authenc.c | 134 + telnet.tproj/commands.c | 2990 +++++++++++++++++ telnet.tproj/defines.h | 84 + telnet.tproj/externs.h | 505 +++ telnet.tproj/fdset.h | 72 + telnet.tproj/general.h | 68 + telnet.tproj/krb4-proto.h | 230 ++ telnet.tproj/main.c | 345 ++ telnet.tproj/network.c | 200 ++ telnet.tproj/ring.c | 385 +++ telnet.tproj/ring.h | 128 + telnet.tproj/sys_bsd.c | 1243 +++++++ telnet.tproj/telnet.1 | 1366 ++++++++ telnet.tproj/telnet.c | 2673 +++++++++++++++ telnet.tproj/terminal.c | 263 ++ telnet.tproj/tn3270.c | 434 +++ telnet.tproj/types.h | 75 + telnet.tproj/utilities.c | 962 ++++++ telnetd.tproj/Makefile | 56 + telnetd.tproj/Makefile.postamble | 111 + telnetd.tproj/Makefile.preamble | 119 + telnetd.tproj/PB.project | 50 + telnetd.tproj/authenc.c | 114 + telnetd.tproj/defs.h | 323 ++ telnetd.tproj/ext.h | 267 ++ telnetd.tproj/global.c | 71 + telnetd.tproj/pathnames.h | 78 + telnetd.tproj/slc.c | 514 +++ telnetd.tproj/state.c | 1635 +++++++++ telnetd.tproj/sys_term.c | 2306 +++++++++++++ telnetd.tproj/telnetd.8 | 607 ++++ telnetd.tproj/telnetd.c | 1640 +++++++++ telnetd.tproj/telnetd.h | 73 + telnetd.tproj/termstat.c | 683 ++++ telnetd.tproj/utility.c | 1215 +++++++ tftp.tproj/Makefile | 52 + tftp.tproj/Makefile.preamble | 3 + tftp.tproj/PB.project | 27 + tftp.tproj/extern.h | 60 + tftp.tproj/main.c | 753 +++++ tftp.tproj/tftp.1 | 173 + tftp.tproj/tftp.c | 474 +++ tftp.tproj/tftpsubs.c | 293 ++ tftp.tproj/tftpsubs.h | 71 + tftpd.tproj/Makefile | 51 + tftpd.tproj/Makefile.postamble | 112 + tftpd.tproj/Makefile.preamble | 121 + tftpd.tproj/PB.project | 41 + tftpd.tproj/tftpd.8 | 106 + tftpd.tproj/tftpd.c | 673 ++++ timed.tproj/Makefile | 44 + timed.tproj/Makefile.postamble | 109 + timed.tproj/Makefile.preamble | 121 + timed.tproj/PB.project | 21 + timed.tproj/timed.tproj/Makefile | 49 + timed.tproj/timed.tproj/Makefile.postamble | 122 + timed.tproj/timed.tproj/Makefile.preamble | 130 + timed.tproj/timed.tproj/PB.project | 38 + timed.tproj/timed.tproj/acksend.c | 155 + timed.tproj/timed.tproj/byteorder.c | 109 + timed.tproj/timed.tproj/candidate.c | 190 ++ timed.tproj/timed.tproj/cksum.c | 110 + timed.tproj/timed.tproj/correct.c | 317 ++ timed.tproj/timed.tproj/extern.h | 112 + timed.tproj/timed.tproj/globals.h | 209 ++ timed.tproj/timed.tproj/master.c | 930 +++++ timed.tproj/timed.tproj/measure.c | 376 +++ timed.tproj/timed.tproj/networkdelta.c | 297 ++ timed.tproj/timed.tproj/pathnames.h | 67 + timed.tproj/timed.tproj/readmsg.c | 511 +++ timed.tproj/timed.tproj/slave.c | 738 ++++ timed.tproj/timed.tproj/timed.8 | 219 ++ timed.tproj/timed.tproj/timed.c | 1006 ++++++ timed.tproj/timedc.tproj/Makefile | 51 + timed.tproj/timedc.tproj/Makefile.postamble | 123 + timed.tproj/timedc.tproj/Makefile.preamble | 130 + timed.tproj/timedc.tproj/PB.project | 27 + timed.tproj/timedc.tproj/cmds.c | 549 +++ timed.tproj/timedc.tproj/cmdtab.c | 80 + timed.tproj/timedc.tproj/extern.h | 75 + timed.tproj/timedc.tproj/h.template | 11 + timed.tproj/timedc.tproj/m.template | 18 + timed.tproj/timedc.tproj/timedc.c | 284 ++ timed.tproj/timedc.tproj/timedc.h | 89 + traceroute.tproj/Makefile | 49 + traceroute.tproj/Makefile.postamble | 110 + traceroute.tproj/Makefile.preamble | 113 + traceroute.tproj/PB.project | 49 + traceroute.tproj/README | 126 + traceroute.tproj/mean.awk | 50 + traceroute.tproj/median.awk | 67 + traceroute.tproj/traceroute.8 | 337 ++ traceroute.tproj/traceroute.c | 858 +++++ trpt.tproj/Makefile | 48 + trpt.tproj/Makefile.postamble | 110 + trpt.tproj/Makefile.preamble | 113 + trpt.tproj/PB.project | 41 + trpt.tproj/trpt.8 | 151 + trpt.tproj/trpt.c | 440 +++ trsp.tproj/Makefile | 48 + trsp.tproj/Makefile.postamble | 110 + trsp.tproj/Makefile.preamble | 113 + trsp.tproj/PB.project | 41 + trsp.tproj/trsp.8 | 141 + trsp.tproj/trsp.c | 458 +++ uucpd.tproj/Makefile | 50 + uucpd.tproj/Makefile.postamble | 111 + uucpd.tproj/Makefile.preamble | 119 + uucpd.tproj/PB.project | 42 + uucpd.tproj/pathnames.h | 61 + uucpd.tproj/uucpd.c | 323 ++ wall.tproj/Makefile | 49 + wall.tproj/Makefile.dist | 8 + wall.tproj/Makefile.postamble | 123 + wall.tproj/Makefile.preamble | 130 + wall.tproj/PB.project | 27 + wall.tproj/ttymsg.c | 183 + wall.tproj/wall.1 | 63 + wall.tproj/wall.c | 221 ++ ypbind.tproj/Makefile | 49 + ypbind.tproj/Makefile.dist | 8 + ypbind.tproj/Makefile.postamble | 108 + ypbind.tproj/Makefile.preamble | 129 + ypbind.tproj/PB.project | 36 + ypbind.tproj/yp.x | 24 + ypbind.tproj/ypbind.c | 1289 +++++++ ypcat.tproj/Makefile | 48 + ypcat.tproj/Makefile.dist | 6 + ypcat.tproj/Makefile.preamble | 2 + ypcat.tproj/PB.project | 36 + ypcat.tproj/ypcat.1 | 70 + ypcat.tproj/ypcat.c | 169 + ypinit.tproj/Makefile | 46 + ypinit.tproj/Makefile.main | 6 + ypinit.tproj/Makefile.yp | 327 ++ ypinit.tproj/ypinit.sh | 402 +++ ypmatch.tproj/Makefile | 48 + ypmatch.tproj/Makefile.dist | 6 + ypmatch.tproj/Makefile.preamble | 2 + ypmatch.tproj/PB.project | 36 + ypmatch.tproj/ypmatch.1 | 71 + ypmatch.tproj/ypmatch.c | 160 + yppoll.tproj/Makefile | 48 + yppoll.tproj/Makefile.dist | 7 + yppoll.tproj/Makefile.preamble | 2 + yppoll.tproj/PB.project | 36 + yppoll.tproj/yppoll.8 | 63 + yppoll.tproj/yppoll.c | 210 ++ yppush.tproj/Makefile | 49 + yppush.tproj/Makefile.postamble | 101 + yppush.tproj/Makefile.preamble | 123 + yppush.tproj/PB.project | 35 + yppush.tproj/ypdb.c | 297 ++ yppush.tproj/ypdb.h | 100 + yppush.tproj/ypdef.h | 94 + yppush.tproj/yplib_host.c | 427 +++ yppush.tproj/yplib_host.h | 82 + yppush.tproj/yppush.8 | 68 + yppush.tproj/yppush.c | 382 +++ yppush.tproj/yppush.h | 133 + yppush.tproj/yppush_err.c | 100 + yppush.tproj/yppush_proc.c | 96 + yppush.tproj/yppush_svc.c | 155 + yppush.tproj/yppush_xdr.c | 171 + ypserv.tproj/Makefile | 52 + ypserv.tproj/Makefile.postamble | 101 + ypserv.tproj/Makefile.preamble | 123 + ypserv.tproj/PB.project | 45 + ypserv.tproj/acl.c | 641 ++++ ypserv.tproj/acl.h | 110 + ypserv.tproj/securenet | 4 + ypserv.tproj/securenet.5 | 74 + ypserv.tproj/yp.h | 612 ++++ ypserv.tproj/ypdb.c | 297 ++ ypserv.tproj/ypdb.h | 100 + ypserv.tproj/ypdef.h | 94 + ypserv.tproj/yplog.c | 149 + ypserv.tproj/yplog.h | 65 + ypserv.tproj/ypserv.acl | 44 + ypserv.tproj/ypserv.acl.5 | 182 + ypserv.tproj/ypserv.c | 559 +++ ypserv.tproj/ypserv_db.c | 811 +++++ ypserv.tproj/ypserv_proc.c | 1061 ++++++ ypserv.tproj/ypserv_xdr.c | 489 +++ ypserv.tproj/ypserv_xdr_v1.c | 130 + ypserv.tproj/ypv1.h | 264 ++ ypset.tproj/Makefile | 48 + ypset.tproj/Makefile.dist | 7 + ypset.tproj/Makefile.preamble | 2 + ypset.tproj/PB.project | 36 + ypset.tproj/ypset.c | 187 ++ ypwhich.tproj/Makefile | 48 + ypwhich.tproj/Makefile.dist | 6 + ypwhich.tproj/Makefile.preamble | 2 + ypwhich.tproj/PB.project | 36 + ypwhich.tproj/ypwhich.1 | 94 + ypwhich.tproj/ypwhich.c | 311 ++ ypxfr.tproj/Makefile | 49 + ypxfr.tproj/Makefile.postamble | 101 + ypxfr.tproj/Makefile.preamble | 123 + ypxfr.tproj/PB.project | 36 + ypxfr.tproj/ypdb.c | 297 ++ ypxfr.tproj/ypdb.h | 100 + ypxfr.tproj/ypdef.h | 94 + ypxfr.tproj/yplib_host.c | 427 +++ ypxfr.tproj/yplib_host.h | 82 + ypxfr.tproj/yplog.c | 149 + ypxfr.tproj/yplog.h | 65 + ypxfr.tproj/ypxfr.8 | 92 + ypxfr.tproj/ypxfr.c | 668 ++++ ypxfr.tproj/ypxfr_1perday.sh | 15 + ypxfr.tproj/ypxfr_1perhour.sh | 11 + ypxfr.tproj/ypxfr_2perday.sh | 10 + ypxfr.tproj/ypxfr_xdr.c | 115 + 729 files changed, 160182 insertions(+) create mode 100644 Makefile create mode 100644 Makefile.include create mode 100644 Makefile.preamble create mode 100644 PB.project create mode 100644 alias/Makefile create mode 100644 alias/Makefile.postamble create mode 100644 alias/Makefile.preamble create mode 100644 alias/PB.project create mode 100644 alias/alias.c create mode 100644 alias/alias.h create mode 100644 alias/alias_cuseeme.c create mode 100644 alias/alias_db.c create mode 100644 alias/alias_ftp.c create mode 100644 alias/alias_irc.c create mode 100644 alias/alias_local.h create mode 100644 alias/alias_nbt.c create mode 100644 alias/alias_proxy.c create mode 100644 alias/alias_util.c create mode 100644 arp.tproj/Makefile create mode 100644 arp.tproj/Makefile.postamble create mode 100644 arp.tproj/Makefile.preamble create mode 100644 arp.tproj/PB.project create mode 100644 arp.tproj/arp.8 create mode 100644 arp.tproj/arp.c create mode 100644 arp.tproj/arp4.4 create mode 100644 bootparams/Makefile create mode 100644 bootparams/Makefile.postamble create mode 100644 bootparams/Makefile.preamble create mode 100644 bootparams/PB.project create mode 100644 bootparams/bootparamd.tproj/Makefile create mode 100644 bootparams/bootparamd.tproj/Makefile.postamble create mode 100644 bootparams/bootparamd.tproj/Makefile.preamble create mode 100644 bootparams/bootparamd.tproj/PB.project create mode 100644 bootparams/bootparamd.tproj/bootparam_proc.c create mode 100644 bootparams/bootparamd.tproj/bootparamd.c create mode 100644 bootparams/bootparams/Makefile create mode 100644 bootparams/bootparams/Makefile.postamble create mode 100644 bootparams/bootparams/Makefile.preamble create mode 100644 bootparams/bootparams/PB.project create mode 100644 bootparams/bootparams/bootparam_prot.x create mode 100644 bootparams/bpwhoami.tproj/Makefile create mode 100644 bootparams/bpwhoami.tproj/Makefile.postamble create mode 100644 bootparams/bpwhoami.tproj/Makefile.preamble create mode 100644 bootparams/bpwhoami.tproj/PB.project create mode 100644 bootparams/bpwhoami.tproj/bpwhoami.c create mode 100644 domainname.tproj/Makefile create mode 100644 domainname.tproj/Makefile.dist create mode 100644 domainname.tproj/PB.project create mode 100644 domainname.tproj/domainname.1 create mode 100644 domainname.tproj/domainname.c create mode 100644 ftp.tproj/Makefile create mode 100644 ftp.tproj/Makefile.postamble create mode 100644 ftp.tproj/Makefile.preamble create mode 100644 ftp.tproj/PB.project create mode 100644 ftp.tproj/cmds.c create mode 100644 ftp.tproj/cmdtab.c create mode 100644 ftp.tproj/domacro.c create mode 100644 ftp.tproj/extern.h create mode 100644 ftp.tproj/ftp.1 create mode 100644 ftp.tproj/ftp.c create mode 100644 ftp.tproj/ftp_var.c create mode 100644 ftp.tproj/ftp_var.h create mode 100644 ftp.tproj/h.template create mode 100644 ftp.tproj/m.template create mode 100644 ftp.tproj/main.c create mode 100644 ftp.tproj/pathnames.h create mode 100644 ftp.tproj/ruserpass.c create mode 100644 ftpd.tproj/Makefile create mode 100644 ftpd.tproj/Makefile.postamble create mode 100644 ftpd.tproj/Makefile.preamble create mode 100644 ftpd.tproj/PB.project create mode 100644 ftpd.tproj/extern.h create mode 100644 ftpd.tproj/ftpcmd.y create mode 100644 ftpd.tproj/ftpd.8 create mode 100644 ftpd.tproj/ftpd.c create mode 100644 ftpd.tproj/logwtmp.c create mode 100644 ftpd.tproj/pathnames.h create mode 100644 ftpd.tproj/popen.c create mode 100644 ftpd.tproj/vers.c create mode 100644 identd.tproj/CREDITS create mode 100644 identd.tproj/Makefile create mode 100644 identd.tproj/Makefile.dist create mode 100644 identd.tproj/Makefile.preamble create mode 100644 identd.tproj/PB.project create mode 100644 identd.tproj/README create mode 100644 identd.tproj/config.c create mode 100644 identd.tproj/error.h create mode 100644 identd.tproj/identd.8 create mode 100644 identd.tproj/identd.c create mode 100644 identd.tproj/identd.h create mode 100644 identd.tproj/netbsd.c create mode 100644 identd.tproj/parse.c create mode 100644 identd.tproj/proxy.c create mode 100644 identd.tproj/version.c create mode 100644 identd.tproj/xpaths.h create mode 100644 ifconfig.tproj/Makefile create mode 100644 ifconfig.tproj/Makefile.dist create mode 100644 ifconfig.tproj/Makefile.postamble create mode 100644 ifconfig.tproj/Makefile.preamble create mode 100644 ifconfig.tproj/PB.project create mode 100644 ifconfig.tproj/ifconfig.8 create mode 100644 ifconfig.tproj/ifconfig.c create mode 100644 ifconfig.tproj/ifconfig.h create mode 100644 ifconfig.tproj/ifmedia.c create mode 100644 inetd.tproj/Makefile create mode 100644 inetd.tproj/Makefile.postamble create mode 100644 inetd.tproj/Makefile.preamble create mode 100644 inetd.tproj/PB.project create mode 100644 inetd.tproj/inetd.8 create mode 100644 inetd.tproj/inetd.c create mode 100644 inetd.tproj/pathnames.h create mode 100644 ipfw.tproj/Makefile create mode 100644 ipfw.tproj/Makefile.postamble create mode 100644 ipfw.tproj/Makefile.preamble create mode 100644 ipfw.tproj/PB.project create mode 100644 ipfw.tproj/ipfw.8 create mode 100644 ipfw.tproj/ipfw.c create mode 100644 logger.tproj/Makefile create mode 100644 logger.tproj/Makefile.postamble create mode 100644 logger.tproj/Makefile.preamble create mode 100644 logger.tproj/PB.project create mode 100644 logger.tproj/h.template create mode 100644 logger.tproj/logger.1 create mode 100644 logger.tproj/logger.c create mode 100644 logger.tproj/m.template create mode 100644 makedbm.tproj/Makefile create mode 100644 makedbm.tproj/Makefile.postamble create mode 100644 makedbm.tproj/Makefile.preamble create mode 100644 makedbm.tproj/PB.project create mode 100644 makedbm.tproj/db.c create mode 100644 makedbm.tproj/db.h create mode 100644 makedbm.tproj/makedbm.8 create mode 100644 makedbm.tproj/makedbm.c create mode 100644 makedbm.tproj/ypdb.c create mode 100644 makedbm.tproj/ypdb.h create mode 100644 makedbm.tproj/ypdef.h create mode 100644 natd.tproj/Makefile create mode 100644 natd.tproj/Makefile.postamble create mode 100644 natd.tproj/Makefile.preamble create mode 100644 natd.tproj/PB.project create mode 100644 natd.tproj/icmp.c create mode 100644 natd.tproj/natd.8 create mode 100644 natd.tproj/natd.c create mode 100644 natd.tproj/natd.h create mode 100644 netstat.tproj/DERIVED_FILES create mode 100644 netstat.tproj/Makefile create mode 100644 netstat.tproj/Makefile.postamble create mode 100644 netstat.tproj/Makefile.preamble create mode 100644 netstat.tproj/PB.project create mode 100644 netstat.tproj/data.c create mode 100644 netstat.tproj/if.c create mode 100644 netstat.tproj/inet.c create mode 100644 netstat.tproj/iso.c create mode 100644 netstat.tproj/main.c create mode 100644 netstat.tproj/mbuf.c create mode 100644 netstat.tproj/mroute.c create mode 100644 netstat.tproj/netstat.1 create mode 100644 netstat.tproj/netstat.h create mode 100644 netstat.tproj/route.c create mode 100644 netstat.tproj/tp_astring.c create mode 100644 netstat.tproj/unix.c create mode 100644 newclient.tproj/Makefile create mode 100644 newclient.tproj/Makefile.preamble create mode 100644 newclient.tproj/PB.project create mode 100644 newclient.tproj/newclient.csh create mode 100644 nfsd.tproj/Makefile create mode 100644 nfsd.tproj/Makefile.dist create mode 100644 nfsd.tproj/Makefile.preamble create mode 100644 nfsd.tproj/PB.project create mode 100644 nfsd.tproj/nfsd.8 create mode 100644 nfsd.tproj/nfsd.c create mode 100644 nfsiod.tproj/Makefile create mode 100644 nfsiod.tproj/Makefile.dist create mode 100644 nfsiod.tproj/Makefile.preamble create mode 100644 nfsiod.tproj/PB.project create mode 100644 nfsiod.tproj/nfsiod.8 create mode 100644 nfsiod.tproj/nfsiod.c create mode 100644 nfsstat.tproj/Makefile create mode 100644 nfsstat.tproj/Makefile.postamble create mode 100644 nfsstat.tproj/Makefile.preamble create mode 100644 nfsstat.tproj/PB.project create mode 100644 nfsstat.tproj/nfsstat.1 create mode 100644 nfsstat.tproj/nfsstat.c create mode 100644 pcap/Makefile create mode 100644 pcap/Makefile.postamble create mode 100644 pcap/Makefile.preamble create mode 100644 pcap/PB.project create mode 100644 pcap/bpf_filter.c create mode 100644 pcap/bpf_image.c create mode 100644 pcap/etherent.c create mode 100644 pcap/ethertype.h create mode 100644 pcap/gencode.c create mode 100644 pcap/gencode.h create mode 100644 pcap/grammar.y create mode 100644 pcap/inet.c create mode 100644 pcap/nametoaddr.c create mode 100644 pcap/optimize.c create mode 100644 pcap/pcap-bpf.c create mode 100644 pcap/pcap-int.h create mode 100644 pcap/pcap-namedb.h create mode 100644 pcap/pcap.c create mode 100644 pcap/pcap.h create mode 100644 pcap/savefile.c create mode 100644 pcap/scanner.l create mode 100644 ping.tproj/Makefile create mode 100644 ping.tproj/Makefile.dist create mode 100644 ping.tproj/Makefile.postamble create mode 100644 ping.tproj/Makefile.preamble create mode 100644 ping.tproj/PB.project create mode 100644 ping.tproj/ping.8 create mode 100644 ping.tproj/ping.c create mode 100644 portmap.tproj/Makefile create mode 100644 portmap.tproj/Makefile.postamble create mode 100644 portmap.tproj/Makefile.preamble create mode 100644 portmap.tproj/PB.project create mode 100644 portmap.tproj/portmap.8 create mode 100644 portmap.tproj/portmap.c create mode 100644 rarpd.tproj/Makefile create mode 100644 rarpd.tproj/Makefile.dist create mode 100644 rarpd.tproj/Makefile.preamble create mode 100644 rarpd.tproj/PB.project create mode 100644 rarpd.tproj/rarpd.8 create mode 100644 rarpd.tproj/rarpd.c create mode 100644 rbootd.tproj/Makefile create mode 100644 rbootd.tproj/Makefile.postamble create mode 100644 rbootd.tproj/Makefile.preamble create mode 100644 rbootd.tproj/PB.project create mode 100644 rbootd.tproj/bpf.c create mode 100644 rbootd.tproj/conf.c create mode 100644 rbootd.tproj/defs.h create mode 100644 rbootd.tproj/parseconf.c create mode 100644 rbootd.tproj/pathnames.h create mode 100644 rbootd.tproj/rbootd.8 create mode 100644 rbootd.tproj/rbootd.c create mode 100644 rbootd.tproj/rmp.h create mode 100644 rbootd.tproj/rmp_var.h create mode 100644 rbootd.tproj/rmpproto.c create mode 100644 rbootd.tproj/utils.c create mode 100644 rcp.tproj/Makefile create mode 100644 rcp.tproj/Makefile.dist create mode 100644 rcp.tproj/Makefile.postamble create mode 100644 rcp.tproj/Makefile.preamble create mode 100644 rcp.tproj/PB.project create mode 100644 rcp.tproj/extern.h create mode 100644 rcp.tproj/pathnames.h create mode 100644 rcp.tproj/rcp.1 create mode 100644 rcp.tproj/rcp.c create mode 100644 rcp.tproj/util.c create mode 100644 revnetgroup.tproj/Makefile create mode 100644 revnetgroup.tproj/Makefile.postamble create mode 100644 revnetgroup.tproj/Makefile.preamble create mode 100644 revnetgroup.tproj/PB.project create mode 100644 revnetgroup.tproj/hash.c create mode 100644 revnetgroup.tproj/hash.h create mode 100644 revnetgroup.tproj/parse_netgroup.c create mode 100644 revnetgroup.tproj/revnetgroup.8 create mode 100644 revnetgroup.tproj/revnetgroup.c create mode 100644 rexecd.tproj/Makefile create mode 100644 rexecd.tproj/Makefile.postamble create mode 100644 rexecd.tproj/Makefile.preamble create mode 100644 rexecd.tproj/PB.project create mode 100644 rexecd.tproj/rexecd.8 create mode 100644 rexecd.tproj/rexecd.c create mode 100644 rlogin.tproj/Makefile create mode 100644 rlogin.tproj/Makefile.postamble create mode 100644 rlogin.tproj/Makefile.preamble create mode 100644 rlogin.tproj/PB.project create mode 100644 rlogin.tproj/des_rw.c create mode 100644 rlogin.tproj/kcmd.c create mode 100644 rlogin.tproj/krb.h create mode 100644 rlogin.tproj/krcmd.c create mode 100644 rlogin.tproj/rlogin.1 create mode 100644 rlogin.tproj/rlogin.c create mode 100644 rlogind.tproj/Makefile create mode 100644 rlogind.tproj/Makefile.postamble create mode 100644 rlogind.tproj/Makefile.preamble create mode 100644 rlogind.tproj/PB.project create mode 100644 rlogind.tproj/pathnames.h create mode 100644 rlogind.tproj/rlogind.8 create mode 100644 rlogind.tproj/rlogind.c create mode 100644 route.tproj/Makefile create mode 100644 route.tproj/Makefile.dist create mode 100644 route.tproj/Makefile.postamble create mode 100644 route.tproj/Makefile.preamble create mode 100644 route.tproj/PB.project create mode 100644 route.tproj/ccitt_addr.c create mode 100644 route.tproj/keywords.h create mode 100644 route.tproj/route.8 create mode 100644 route.tproj/route.c create mode 100644 routed.tproj/Makefile create mode 100644 routed.tproj/Makefile.dist create mode 100644 routed.tproj/Makefile.preamble create mode 100644 routed.tproj/PB.project create mode 100644 routed.tproj/af.c create mode 100644 routed.tproj/af.h create mode 100644 routed.tproj/defs.c create mode 100644 routed.tproj/defs.h create mode 100644 routed.tproj/if.c create mode 100644 routed.tproj/inet.c create mode 100644 routed.tproj/input.c create mode 100644 routed.tproj/interface.h create mode 100644 routed.tproj/main.c create mode 100644 routed.tproj/output.c create mode 100644 routed.tproj/pathnames.h create mode 100644 routed.tproj/routed.8 create mode 100644 routed.tproj/startup.c create mode 100644 routed.tproj/table.h create mode 100644 routed.tproj/tables.c create mode 100644 routed.tproj/timer.c create mode 100644 routed.tproj/trace.c create mode 100644 routed.tproj/trace.h create mode 100644 rpc_yppasswdd.tproj/Makefile create mode 100644 rpc_yppasswdd.tproj/Makefile.postamble create mode 100644 rpc_yppasswdd.tproj/Makefile.preamble create mode 100644 rpc_yppasswdd.tproj/PB.project create mode 100644 rpc_yppasswdd.tproj/passwd.c create mode 100644 rpc_yppasswdd.tproj/rpc.yppasswdd.8 create mode 100644 rpc_yppasswdd.tproj/rpc.yppasswdd.c create mode 100644 rpc_yppasswdd.tproj/yppasswd.h create mode 100644 rpc_yppasswdd.tproj/yppasswdd_mkpw.c create mode 100644 rpc_yppasswdd.tproj/yppasswdd_proc.c create mode 100644 rpcinfo.tproj/Makefile create mode 100644 rpcinfo.tproj/Makefile.postamble create mode 100644 rpcinfo.tproj/Makefile.preamble create mode 100644 rpcinfo.tproj/PB.project create mode 100644 rpcinfo.tproj/h.template create mode 100644 rpcinfo.tproj/m.template create mode 100644 rpcinfo.tproj/rpcinfo.c create mode 100644 rsh.tproj/Makefile create mode 100644 rsh.tproj/Makefile.postamble create mode 100644 rsh.tproj/Makefile.preamble create mode 100644 rsh.tproj/PB.project create mode 100644 rsh.tproj/pathnames.h create mode 100644 rsh.tproj/rsh.1 create mode 100644 rsh.tproj/rsh.c create mode 100644 rshd.tproj/Makefile create mode 100644 rshd.tproj/Makefile.postamble create mode 100644 rshd.tproj/Makefile.preamble create mode 100644 rshd.tproj/PB.project create mode 100644 rshd.tproj/rshd.8 create mode 100644 rshd.tproj/rshd.c create mode 100644 ruptime.tproj/Makefile create mode 100644 ruptime.tproj/Makefile.dist create mode 100644 ruptime.tproj/Makefile.postamble create mode 100644 ruptime.tproj/Makefile.preamble create mode 100644 ruptime.tproj/PB.project create mode 100644 ruptime.tproj/h.template create mode 100644 ruptime.tproj/m.template create mode 100644 ruptime.tproj/ruptime.1 create mode 100644 ruptime.tproj/ruptime.c create mode 100644 rwho.tproj/Makefile create mode 100644 rwho.tproj/Makefile.dist create mode 100644 rwho.tproj/Makefile.postamble create mode 100644 rwho.tproj/Makefile.preamble create mode 100644 rwho.tproj/PB.project create mode 100644 rwho.tproj/rwho.1 create mode 100644 rwho.tproj/rwho.c create mode 100644 rwhod.tproj/Makefile create mode 100644 rwhod.tproj/Makefile.postamble create mode 100644 rwhod.tproj/Makefile.preamble create mode 100644 rwhod.tproj/PB.project create mode 100644 rwhod.tproj/rwhod.8 create mode 100644 rwhod.tproj/rwhod.c create mode 100644 slattach.tproj/Makefile create mode 100644 slattach.tproj/Makefile.dist create mode 100644 slattach.tproj/Makefile.preamble create mode 100644 slattach.tproj/PB.project create mode 100644 slattach.tproj/slattach.8 create mode 100644 slattach.tproj/slattach.c create mode 100644 sliplogin.tproj/Makefile create mode 100644 sliplogin.tproj/Makefile.postamble create mode 100644 sliplogin.tproj/Makefile.preamble create mode 100644 sliplogin.tproj/PB.project create mode 100644 sliplogin.tproj/pathnames.h create mode 100644 sliplogin.tproj/slip.hosts create mode 100644 sliplogin.tproj/slip.login create mode 100644 sliplogin.tproj/sliplogin.8 create mode 100644 sliplogin.tproj/sliplogin.c create mode 100644 spray.tproj/Makefile create mode 100644 spray.tproj/Makefile.dist create mode 100644 spray.tproj/Makefile.postamble create mode 100644 spray.tproj/Makefile.preamble create mode 100644 spray.tproj/PB.project create mode 100644 spray.tproj/spray.c create mode 100644 spray.tproj/spray.x create mode 100644 startslip.tproj/Makefile create mode 100644 startslip.tproj/Makefile.dist create mode 100644 startslip.tproj/Makefile.preamble create mode 100644 startslip.tproj/PB.project create mode 100644 startslip.tproj/startslip.1 create mode 100644 startslip.tproj/startslip.c create mode 100644 stdethers.tproj/Makefile create mode 100644 stdethers.tproj/Makefile.postamble create mode 100644 stdethers.tproj/Makefile.preamble create mode 100644 stdethers.tproj/PB.project create mode 100644 stdethers.tproj/stdethers.8 create mode 100644 stdethers.tproj/stdethers.c create mode 100644 stdhosts.tproj/Makefile create mode 100644 stdhosts.tproj/Makefile.postamble create mode 100644 stdhosts.tproj/Makefile.preamble create mode 100644 stdhosts.tproj/PB.project create mode 100644 stdhosts.tproj/stdhosts.8 create mode 100644 stdhosts.tproj/stdhosts.c create mode 100644 syslogd.tproj/Makefile create mode 100644 syslogd.tproj/Makefile.postamble create mode 100644 syslogd.tproj/Makefile.preamble create mode 100644 syslogd.tproj/PB.project create mode 100644 syslogd.tproj/pathnames.h create mode 100644 syslogd.tproj/syslog.conf.5 create mode 100644 syslogd.tproj/syslogd.8 create mode 100644 syslogd.tproj/syslogd.c create mode 100644 talk.tproj/Makefile create mode 100644 talk.tproj/Makefile.preamble create mode 100644 talk.tproj/PB.project create mode 100644 talk.tproj/ctl.c create mode 100644 talk.tproj/ctl_transact.c create mode 100644 talk.tproj/display.c create mode 100644 talk.tproj/get_addrs.c create mode 100644 talk.tproj/get_names.c create mode 100644 talk.tproj/init_disp.c create mode 100644 talk.tproj/invite.c create mode 100644 talk.tproj/io.c create mode 100644 talk.tproj/look_up.c create mode 100644 talk.tproj/msgs.c create mode 100644 talk.tproj/talk.1 create mode 100644 talk.tproj/talk.c create mode 100644 talk.tproj/talk.h create mode 100644 talk.tproj/talk_ctl.h create mode 100644 talkd.tproj/Makefile create mode 100644 talkd.tproj/Makefile.dist create mode 100644 talkd.tproj/Makefile.postamble create mode 100644 talkd.tproj/Makefile.preamble create mode 100644 talkd.tproj/PB.project create mode 100644 talkd.tproj/announce.c create mode 100644 talkd.tproj/print.c create mode 100644 talkd.tproj/process.c create mode 100644 talkd.tproj/table.c create mode 100644 talkd.tproj/talkd.8 create mode 100644 talkd.tproj/talkd.c create mode 100644 talkd.tproj/talkd.h create mode 100644 tcpdump.tproj/Makefile create mode 100644 tcpdump.tproj/Makefile.postamble create mode 100644 tcpdump.tproj/Makefile.preamble create mode 100644 tcpdump.tproj/PB.project create mode 100644 tcpdump.tproj/addrtoname.c create mode 100644 tcpdump.tproj/addrtoname.h create mode 100644 tcpdump.tproj/appletalk.h create mode 100644 tcpdump.tproj/bootp.h create mode 100644 tcpdump.tproj/bpf_dump.c create mode 100644 tcpdump.tproj/decnet.h create mode 100644 tcpdump.tproj/ethertype.h create mode 100644 tcpdump.tproj/extract.h create mode 100644 tcpdump.tproj/fddi.h create mode 100644 tcpdump.tproj/gnuc.h create mode 100644 tcpdump.tproj/igrp.h create mode 100644 tcpdump.tproj/interface.h create mode 100644 tcpdump.tproj/ipx.h create mode 100644 tcpdump.tproj/llc.h create mode 100644 tcpdump.tproj/machdep.c create mode 100644 tcpdump.tproj/machdep.h create mode 100644 tcpdump.tproj/mib.h create mode 100644 tcpdump.tproj/netbios.h create mode 100644 tcpdump.tproj/nfs.h create mode 100644 tcpdump.tproj/nfsfh.h create mode 100644 tcpdump.tproj/nfsv2.h create mode 100644 tcpdump.tproj/ntp.h create mode 100644 tcpdump.tproj/os-solaris2.h create mode 100644 tcpdump.tproj/os-sunos4.h create mode 100644 tcpdump.tproj/os-ultrix4.h create mode 100644 tcpdump.tproj/ospf.h create mode 100644 tcpdump.tproj/parsenfsfh.c create mode 100644 tcpdump.tproj/print-arp.c create mode 100644 tcpdump.tproj/print-atalk.c create mode 100644 tcpdump.tproj/print-atm.c create mode 100644 tcpdump.tproj/print-bootp.c create mode 100644 tcpdump.tproj/print-decnet.c create mode 100644 tcpdump.tproj/print-domain.c create mode 100644 tcpdump.tproj/print-dvmrp.c create mode 100644 tcpdump.tproj/print-egp.c create mode 100644 tcpdump.tproj/print-ether.c create mode 100644 tcpdump.tproj/print-fddi.c create mode 100644 tcpdump.tproj/print-gre.c create mode 100644 tcpdump.tproj/print-icmp.c create mode 100644 tcpdump.tproj/print-igrp.c create mode 100644 tcpdump.tproj/print-ip.c create mode 100644 tcpdump.tproj/print-ipx.c create mode 100644 tcpdump.tproj/print-isoclns.c create mode 100644 tcpdump.tproj/print-krb.c create mode 100644 tcpdump.tproj/print-llc.c create mode 100644 tcpdump.tproj/print-netbios.c create mode 100644 tcpdump.tproj/print-nfs.c create mode 100644 tcpdump.tproj/print-ntp.c create mode 100644 tcpdump.tproj/print-null.c create mode 100644 tcpdump.tproj/print-ospf.c create mode 100644 tcpdump.tproj/print-pim.c create mode 100644 tcpdump.tproj/print-ppp.c create mode 100644 tcpdump.tproj/print-rip.c create mode 100644 tcpdump.tproj/print-skip.c create mode 100644 tcpdump.tproj/print-sl.c create mode 100644 tcpdump.tproj/print-snmp.c create mode 100644 tcpdump.tproj/print-sunrpc.c create mode 100644 tcpdump.tproj/print-tcp.c create mode 100644 tcpdump.tproj/print-tftp.c create mode 100644 tcpdump.tproj/print-udp.c create mode 100644 tcpdump.tproj/print-wb.c create mode 100644 tcpdump.tproj/strcasecmp.c create mode 100644 tcpdump.tproj/tcpdump.c create mode 100644 tcpdump.tproj/util.c create mode 100644 tcpdump.tproj/version.c create mode 100644 tcpdump.tproj/vfprintf.c create mode 100644 telnet.tproj/Makefile create mode 100644 telnet.tproj/Makefile.dist create mode 100644 telnet.tproj/Makefile.preamble create mode 100644 telnet.tproj/PB.project create mode 100644 telnet.tproj/README create mode 100644 telnet.tproj/authenc.c create mode 100644 telnet.tproj/commands.c create mode 100644 telnet.tproj/defines.h create mode 100644 telnet.tproj/externs.h create mode 100644 telnet.tproj/fdset.h create mode 100644 telnet.tproj/general.h create mode 100644 telnet.tproj/krb4-proto.h create mode 100644 telnet.tproj/main.c create mode 100644 telnet.tproj/network.c create mode 100644 telnet.tproj/ring.c create mode 100644 telnet.tproj/ring.h create mode 100644 telnet.tproj/sys_bsd.c create mode 100644 telnet.tproj/telnet.1 create mode 100644 telnet.tproj/telnet.c create mode 100644 telnet.tproj/terminal.c create mode 100644 telnet.tproj/tn3270.c create mode 100644 telnet.tproj/types.h create mode 100644 telnet.tproj/utilities.c create mode 100644 telnetd.tproj/Makefile create mode 100644 telnetd.tproj/Makefile.postamble create mode 100644 telnetd.tproj/Makefile.preamble create mode 100644 telnetd.tproj/PB.project create mode 100644 telnetd.tproj/authenc.c create mode 100644 telnetd.tproj/defs.h create mode 100644 telnetd.tproj/ext.h create mode 100644 telnetd.tproj/global.c create mode 100644 telnetd.tproj/pathnames.h create mode 100644 telnetd.tproj/slc.c create mode 100644 telnetd.tproj/state.c create mode 100644 telnetd.tproj/sys_term.c create mode 100644 telnetd.tproj/telnetd.8 create mode 100644 telnetd.tproj/telnetd.c create mode 100644 telnetd.tproj/telnetd.h create mode 100644 telnetd.tproj/termstat.c create mode 100644 telnetd.tproj/utility.c create mode 100644 tftp.tproj/Makefile create mode 100644 tftp.tproj/Makefile.preamble create mode 100644 tftp.tproj/PB.project create mode 100644 tftp.tproj/extern.h create mode 100644 tftp.tproj/main.c create mode 100644 tftp.tproj/tftp.1 create mode 100644 tftp.tproj/tftp.c create mode 100644 tftp.tproj/tftpsubs.c create mode 100644 tftp.tproj/tftpsubs.h create mode 100644 tftpd.tproj/Makefile create mode 100644 tftpd.tproj/Makefile.postamble create mode 100644 tftpd.tproj/Makefile.preamble create mode 100644 tftpd.tproj/PB.project create mode 100644 tftpd.tproj/tftpd.8 create mode 100644 tftpd.tproj/tftpd.c create mode 100644 timed.tproj/Makefile create mode 100644 timed.tproj/Makefile.postamble create mode 100644 timed.tproj/Makefile.preamble create mode 100644 timed.tproj/PB.project create mode 100644 timed.tproj/timed.tproj/Makefile create mode 100644 timed.tproj/timed.tproj/Makefile.postamble create mode 100644 timed.tproj/timed.tproj/Makefile.preamble create mode 100644 timed.tproj/timed.tproj/PB.project create mode 100644 timed.tproj/timed.tproj/acksend.c create mode 100644 timed.tproj/timed.tproj/byteorder.c create mode 100644 timed.tproj/timed.tproj/candidate.c create mode 100644 timed.tproj/timed.tproj/cksum.c create mode 100644 timed.tproj/timed.tproj/correct.c create mode 100644 timed.tproj/timed.tproj/extern.h create mode 100644 timed.tproj/timed.tproj/globals.h create mode 100644 timed.tproj/timed.tproj/master.c create mode 100644 timed.tproj/timed.tproj/measure.c create mode 100644 timed.tproj/timed.tproj/networkdelta.c create mode 100644 timed.tproj/timed.tproj/pathnames.h create mode 100644 timed.tproj/timed.tproj/readmsg.c create mode 100644 timed.tproj/timed.tproj/slave.c create mode 100644 timed.tproj/timed.tproj/timed.8 create mode 100644 timed.tproj/timed.tproj/timed.c create mode 100644 timed.tproj/timedc.tproj/Makefile create mode 100644 timed.tproj/timedc.tproj/Makefile.postamble create mode 100644 timed.tproj/timedc.tproj/Makefile.preamble create mode 100644 timed.tproj/timedc.tproj/PB.project create mode 100644 timed.tproj/timedc.tproj/cmds.c create mode 100644 timed.tproj/timedc.tproj/cmdtab.c create mode 100644 timed.tproj/timedc.tproj/extern.h create mode 100644 timed.tproj/timedc.tproj/h.template create mode 100644 timed.tproj/timedc.tproj/m.template create mode 100644 timed.tproj/timedc.tproj/timedc.c create mode 100644 timed.tproj/timedc.tproj/timedc.h create mode 100644 traceroute.tproj/Makefile create mode 100644 traceroute.tproj/Makefile.postamble create mode 100644 traceroute.tproj/Makefile.preamble create mode 100644 traceroute.tproj/PB.project create mode 100644 traceroute.tproj/README create mode 100644 traceroute.tproj/mean.awk create mode 100644 traceroute.tproj/median.awk create mode 100644 traceroute.tproj/traceroute.8 create mode 100644 traceroute.tproj/traceroute.c create mode 100644 trpt.tproj/Makefile create mode 100644 trpt.tproj/Makefile.postamble create mode 100644 trpt.tproj/Makefile.preamble create mode 100644 trpt.tproj/PB.project create mode 100644 trpt.tproj/trpt.8 create mode 100644 trpt.tproj/trpt.c create mode 100644 trsp.tproj/Makefile create mode 100644 trsp.tproj/Makefile.postamble create mode 100644 trsp.tproj/Makefile.preamble create mode 100644 trsp.tproj/PB.project create mode 100644 trsp.tproj/trsp.8 create mode 100644 trsp.tproj/trsp.c create mode 100644 uucpd.tproj/Makefile create mode 100644 uucpd.tproj/Makefile.postamble create mode 100644 uucpd.tproj/Makefile.preamble create mode 100644 uucpd.tproj/PB.project create mode 100644 uucpd.tproj/pathnames.h create mode 100644 uucpd.tproj/uucpd.c create mode 100644 wall.tproj/Makefile create mode 100644 wall.tproj/Makefile.dist create mode 100644 wall.tproj/Makefile.postamble create mode 100644 wall.tproj/Makefile.preamble create mode 100644 wall.tproj/PB.project create mode 100644 wall.tproj/ttymsg.c create mode 100644 wall.tproj/wall.1 create mode 100644 wall.tproj/wall.c create mode 100644 ypbind.tproj/Makefile create mode 100644 ypbind.tproj/Makefile.dist create mode 100644 ypbind.tproj/Makefile.postamble create mode 100644 ypbind.tproj/Makefile.preamble create mode 100644 ypbind.tproj/PB.project create mode 100644 ypbind.tproj/yp.x create mode 100644 ypbind.tproj/ypbind.c create mode 100644 ypcat.tproj/Makefile create mode 100644 ypcat.tproj/Makefile.dist create mode 100644 ypcat.tproj/Makefile.preamble create mode 100644 ypcat.tproj/PB.project create mode 100644 ypcat.tproj/ypcat.1 create mode 100644 ypcat.tproj/ypcat.c create mode 100644 ypinit.tproj/Makefile create mode 100644 ypinit.tproj/Makefile.main create mode 100644 ypinit.tproj/Makefile.yp create mode 100644 ypinit.tproj/ypinit.sh create mode 100644 ypmatch.tproj/Makefile create mode 100644 ypmatch.tproj/Makefile.dist create mode 100644 ypmatch.tproj/Makefile.preamble create mode 100644 ypmatch.tproj/PB.project create mode 100644 ypmatch.tproj/ypmatch.1 create mode 100644 ypmatch.tproj/ypmatch.c create mode 100644 yppoll.tproj/Makefile create mode 100644 yppoll.tproj/Makefile.dist create mode 100644 yppoll.tproj/Makefile.preamble create mode 100644 yppoll.tproj/PB.project create mode 100644 yppoll.tproj/yppoll.8 create mode 100644 yppoll.tproj/yppoll.c create mode 100644 yppush.tproj/Makefile create mode 100644 yppush.tproj/Makefile.postamble create mode 100644 yppush.tproj/Makefile.preamble create mode 100644 yppush.tproj/PB.project create mode 100644 yppush.tproj/ypdb.c create mode 100644 yppush.tproj/ypdb.h create mode 100644 yppush.tproj/ypdef.h create mode 100644 yppush.tproj/yplib_host.c create mode 100644 yppush.tproj/yplib_host.h create mode 100644 yppush.tproj/yppush.8 create mode 100644 yppush.tproj/yppush.c create mode 100644 yppush.tproj/yppush.h create mode 100644 yppush.tproj/yppush_err.c create mode 100644 yppush.tproj/yppush_proc.c create mode 100644 yppush.tproj/yppush_svc.c create mode 100644 yppush.tproj/yppush_xdr.c create mode 100644 ypserv.tproj/Makefile create mode 100644 ypserv.tproj/Makefile.postamble create mode 100644 ypserv.tproj/Makefile.preamble create mode 100644 ypserv.tproj/PB.project create mode 100644 ypserv.tproj/acl.c create mode 100644 ypserv.tproj/acl.h create mode 100644 ypserv.tproj/securenet create mode 100644 ypserv.tproj/securenet.5 create mode 100644 ypserv.tproj/yp.h create mode 100644 ypserv.tproj/ypdb.c create mode 100644 ypserv.tproj/ypdb.h create mode 100644 ypserv.tproj/ypdef.h create mode 100644 ypserv.tproj/yplog.c create mode 100644 ypserv.tproj/yplog.h create mode 100644 ypserv.tproj/ypserv.acl create mode 100644 ypserv.tproj/ypserv.acl.5 create mode 100644 ypserv.tproj/ypserv.c create mode 100644 ypserv.tproj/ypserv_db.c create mode 100644 ypserv.tproj/ypserv_proc.c create mode 100644 ypserv.tproj/ypserv_xdr.c create mode 100644 ypserv.tproj/ypserv_xdr_v1.c create mode 100644 ypserv.tproj/ypv1.h create mode 100644 ypset.tproj/Makefile create mode 100644 ypset.tproj/Makefile.dist create mode 100644 ypset.tproj/Makefile.preamble create mode 100644 ypset.tproj/PB.project create mode 100644 ypset.tproj/ypset.c create mode 100644 ypwhich.tproj/Makefile create mode 100644 ypwhich.tproj/Makefile.dist create mode 100644 ypwhich.tproj/Makefile.preamble create mode 100644 ypwhich.tproj/PB.project create mode 100644 ypwhich.tproj/ypwhich.1 create mode 100644 ypwhich.tproj/ypwhich.c create mode 100644 ypxfr.tproj/Makefile create mode 100644 ypxfr.tproj/Makefile.postamble create mode 100644 ypxfr.tproj/Makefile.preamble create mode 100644 ypxfr.tproj/PB.project create mode 100644 ypxfr.tproj/ypdb.c create mode 100644 ypxfr.tproj/ypdb.h create mode 100644 ypxfr.tproj/ypdef.h create mode 100644 ypxfr.tproj/yplib_host.c create mode 100644 ypxfr.tproj/yplib_host.h create mode 100644 ypxfr.tproj/yplog.c create mode 100644 ypxfr.tproj/yplog.h create mode 100644 ypxfr.tproj/ypxfr.8 create mode 100644 ypxfr.tproj/ypxfr.c create mode 100755 ypxfr.tproj/ypxfr_1perday.sh create mode 100755 ypxfr.tproj/ypxfr_1perhour.sh create mode 100755 ypxfr.tproj/ypxfr_2perday.sh create mode 100644 ypxfr.tproj/ypxfr_xdr.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b8719cd --- /dev/null +++ b/Makefile @@ -0,0 +1,59 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = network_cmds + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Aggregate + +SUBPROJECTS = timed.tproj bootparams + +TOOLS = arp.tproj domainname.tproj ftp.tproj ftpd.tproj identd.tproj\ + ifconfig.tproj inetd.tproj logger.tproj netstat.tproj\ + nfsd.tproj nfsiod.tproj nfsstat.tproj ping.tproj portmap.tproj\ + rarpd.tproj rbootd.tproj rcp.tproj rexecd.tproj rlogin.tproj\ + rlogind.tproj route.tproj routed.tproj rpcinfo.tproj rsh.tproj\ + rshd.tproj ruptime.tproj rwho.tproj rwhod.tproj slattach.tproj\ + sliplogin.tproj spray.tproj startslip.tproj syslogd.tproj\ + talk.tproj talkd.tproj tcpdump.tproj telnet.tproj\ + telnetd.tproj tftp.tproj tftpd.tproj traceroute.tproj\ + trpt.tproj trsp.tproj uucpd.tproj wall.tproj ypbind.tproj\ + ypcat.tproj ypmatch.tproj yppoll.tproj yppush.tproj\ + ypserv.tproj ypset.tproj ypwhich.tproj ypxfr.tproj\ + makedbm.tproj revnetgroup.tproj rpc_yppasswdd.tproj\ + stdethers.tproj stdhosts.tproj natd.tproj ipfw.tproj + +LIBRARIES = alias pcap + +LEGACIES = newclient.tproj ypinit.tproj + +OTHERSRCS = Makefile Makefile.include Makefile.preamble + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = aggregate.make +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/Makefile.include b/Makefile.include new file mode 100644 index 0000000..ee97aa2 --- /dev/null +++ b/Makefile.include @@ -0,0 +1,12 @@ +## +## Temporary flags for static Teflon builds +## + +#CODE_GEN_STYLE = STATIC +#OTHER_LDFLAGS = -nostdlib /lib/crt0.o -L/tmp/lennart/lib -L/usr/local/lib +#OTHER_LIBS = -linfo -lc -lm + +#OTHER_LDFLAGS = -nostdlib /lib/crt1.o +#OTHER_LIBS = -framework System + +CHFLAGS = true # until we really have chflags on our system diff --git a/Makefile.preamble b/Makefile.preamble new file mode 100644 index 0000000..a6b1e76 --- /dev/null +++ b/Makefile.preamble @@ -0,0 +1 @@ +CLEAN_ALL_SUBPROJECTS = YES diff --git a/PB.project b/PB.project new file mode 100644 index 0000000..3015bd3 --- /dev/null +++ b/PB.project @@ -0,0 +1,82 @@ +{ + FILESTABLE = { + OTHER_SOURCES = (Makefile, Makefile.include, Makefile.preamble); + SUBPROJECTS = ( + alias, + pcap, + timed.tproj, + arp.tproj, + bootparams, + domainname.tproj, + ftp.tproj, + ftpd.tproj, + identd.tproj, + ifconfig.tproj, + inetd.tproj, + logger.tproj, + netstat.tproj, + newclient.tproj, + nfsd.tproj, + nfsiod.tproj, + nfsstat.tproj, + ping.tproj, + portmap.tproj, + rarpd.tproj, + rbootd.tproj, + rcp.tproj, + rexecd.tproj, + rlogin.tproj, + rlogind.tproj, + route.tproj, + routed.tproj, + rpcinfo.tproj, + rsh.tproj, + rshd.tproj, + ruptime.tproj, + rwho.tproj, + rwhod.tproj, + slattach.tproj, + sliplogin.tproj, + spray.tproj, + startslip.tproj, + syslogd.tproj, + talk.tproj, + talkd.tproj, + tcpdump.tproj, + telnet.tproj, + telnetd.tproj, + tftp.tproj, + tftpd.tproj, + traceroute.tproj, + trpt.tproj, + trsp.tproj, + uucpd.tproj, + wall.tproj, + ypbind.tproj, + ypcat.tproj, + ypinit.tproj, + ypmatch.tproj, + yppoll.tproj, + yppush.tproj, + ypserv.tproj, + ypset.tproj, + ypwhich.tproj, + ypxfr.tproj, + makedbm.tproj, + revnetgroup.tproj, + rpc_yppasswdd.tproj, + stdethers.tproj, + stdhosts.tproj, + natd.tproj, + ipfw.tproj + ); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /usr/bin/gnumake; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PROJECTNAME = network_cmds; + PROJECTTYPE = Aggregate; + PROJECTVERSION = 2.8; +} diff --git a/alias/Makefile b/alias/Makefile new file mode 100644 index 0000000..f844cc3 --- /dev/null +++ b/alias/Makefile @@ -0,0 +1,59 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = alias + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Library + +HFILES = alias.h alias_local.h + +CFILES = alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c\ + alias_nbt.c alias_proxy.c alias_util.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CURRENTLY_ACTIVE_VERSION = YES +DEPLOY_WITH_VERSION_NAME = A +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = library.make +NEXTSTEP_INSTALLDIR = /usr/lib +WINDOWS_INSTALLDIR = /Developer/Libraries +PDO_UNIX_INSTALLDIR = /usr/lib +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +PROJECT_HEADERS = alias.h + + + +WINDOWS_PUBLIC_HEADERS_DIR = /Developer/Headers/$(NAME) + +PDO_UNIX_PUBLIC_HEADERS_DIR = /Developer/Headers/$(NAME) + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/alias/Makefile.postamble b/alias/Makefile.postamble new file mode 100644 index 0000000..411cde6 --- /dev/null +++ b/alias/Makefile.postamble @@ -0,0 +1,100 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/alias/Makefile.preamble b/alias/Makefile.preamble new file mode 100644 index 0000000..f02898c --- /dev/null +++ b/alias/Makefile.preamble @@ -0,0 +1,138 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex +OTHER_LDFLAGS += -seg1addr 0xf9300000 + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +DSTROOT = $(HOME) diff --git a/alias/PB.project b/alias/PB.project new file mode 100644 index 0000000..e87cc27 --- /dev/null +++ b/alias/PB.project @@ -0,0 +1,39 @@ +{ + CURRENTLY_ACTIVE_VERSION = YES; + DEPLOY_WITH_VERSION_NAME = A; + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + H_FILES = (alias.h, alias_local.h); + OTHER_LINKED = ( + alias.c, + alias_cuseeme.c, + alias_db.c, + alias_ftp.c, + alias_irc.c, + alias_nbt.c, + alias_proxy.c, + alias_util.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + PROJECT_HEADERS = (alias.h); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/lib; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /usr/lib; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PDO_UNIX_PUBLICHEADERSDIR = "/Developer/Headers/$(NAME)"; + PROJECTNAME = alias; + PROJECTTYPE = Library; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Developer/Libraries; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + WINDOWS_PUBLICHEADERSDIR = "/Developer/Headers/$(NAME)"; +} diff --git a/alias/alias.c b/alias/alias.c new file mode 100644 index 0000000..10e0ccc --- /dev/null +++ b/alias/alias.c @@ -0,0 +1,1318 @@ +/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- */ +/* + Alias.c provides supervisory control for the functions of the + packet aliasing software. It consists of routines to monitor + TCP connection state, protocol-specific aliasing routines, + fragment handling and the following outside world functional + interfaces: SaveFragmentPtr, GetFragmentPtr, FragmentAliasIn, + PacketAliasIn and PacketAliasOut. + + The other C program files are briefly described. The data + structure framework which holds information needed to translate + packets is encapsulated in alias_db.c. Data is accessed by + function calls, so other segments of the program need not know + about the underlying data structures. Alias_ftp.c contains + special code for modifying the ftp PORT command used to establish + data connections, while alias_irc.c do the same for IRC + DCC. Alias_util.c contains a few utility routines. + + This software is placed into the public domain with no restrictions + on its distribution. + + Version 1.0 August, 1996 (cjm) + + Version 1.1 August 20, 1996 (cjm) + PPP host accepts incoming connections for ports 0 to 1023. + (Gary Roberts pointed out the need to handle incoming + connections.) + + Version 1.2 September 7, 1996 (cjm) + Fragment handling error in alias_db.c corrected. + (Tom Torrance helped fix this problem.) + + Version 1.4 September 16, 1996 (cjm) + - A more generalized method for handling incoming + connections, without the 0-1023 restriction, is + implemented in alias_db.c + - Improved ICMP support in alias.c. Traceroute + packet streams can now be correctly aliased. + - TCP connection closing logic simplified in + alias.c and now allows for additional 1 minute + "grace period" after FIN or RST is observed. + + Version 1.5 September 17, 1996 (cjm) + Corrected error in handling incoming UDP packets with 0 checksum. + (Tom Torrance helped fix this problem.) + + Version 1.6 September 18, 1996 (cjm) + Simplified ICMP aliasing scheme. Should now support + traceroute from Win95 as well as FreeBSD. + + Version 1.7 January 9, 1997 (cjm) + - Out-of-order fragment handling. + - IP checksum error fixed for ftp transfers + from aliasing host. + - Integer return codes added to all + aliasing/de-aliasing functions. + - Some obsolete comments cleaned up. + - Differential checksum computations for + IP header (TCP, UDP and ICMP were already + differential). + + Version 2.1 May 1997 (cjm) + - Added support for outgoing ICMP error + messages. + - Added two functions PacketAliasIn2() + and PacketAliasOut2() for dynamic address + control (e.g. round-robin allocation of + incoming packets). + + Version 2.2 July 1997 (cjm) + - Rationalized API function names to begin + with "PacketAlias..." + - Eliminated PacketAliasIn2() and + PacketAliasOut2() as poorly conceived. + + Version 2.3 Dec 1998 (dillon) + - Major bounds checking additions, see FreeBSD/CVS + + See HISTORY file for additional revisions. + +*/ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#ifndef IPPROTO_GRE +#define IPPROTO_GRE 47 +#endif + +#include "alias_local.h" +#include "alias.h" + +#define NETBIOS_NS_PORT_NUMBER 137 +#define NETBIOS_DGM_PORT_NUMBER 138 +#define FTP_CONTROL_PORT_NUMBER 21 +#define IRC_CONTROL_PORT_NUMBER_1 6667 +#define IRC_CONTROL_PORT_NUMBER_2 6668 +#define CUSEEME_PORT_NUMBER 7648 + + + + +/* TCP Handling Routines + + TcpMonitorIn() -- These routines monitor TCP connections, and + TcpMonitorOut() delete a link when a connection is closed. + +These routines look for SYN, ACK and RST flags to determine when TCP +connections open and close. When a TCP connection closes, the data +structure containing packet aliasing information is deleted after +a timeout period. +*/ + +/* Local prototypes */ +static void TcpMonitorIn(struct ip *, struct alias_link *); + +static void TcpMonitorOut(struct ip *, struct alias_link *); + + +static void +TcpMonitorIn(struct ip *pip, struct alias_link *link) +{ + struct tcphdr *tc; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + + switch (GetStateIn(link)) + { + case ALIAS_TCP_STATE_NOT_CONNECTED: + if (tc->th_flags & TH_SYN) + SetStateIn(link, ALIAS_TCP_STATE_CONNECTED); + break; + case ALIAS_TCP_STATE_CONNECTED: + if (tc->th_flags & TH_FIN + || tc->th_flags & TH_RST) + SetStateIn(link, ALIAS_TCP_STATE_DISCONNECTED); + break; + } +} + +static void +TcpMonitorOut(struct ip *pip, struct alias_link *link) +{ + struct tcphdr *tc; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + + switch (GetStateOut(link)) + { + case ALIAS_TCP_STATE_NOT_CONNECTED: + if (tc->th_flags & TH_SYN) + SetStateOut(link, ALIAS_TCP_STATE_CONNECTED); + break; + case ALIAS_TCP_STATE_CONNECTED: + if (tc->th_flags & TH_FIN + || tc->th_flags & TH_RST) + SetStateOut(link, ALIAS_TCP_STATE_DISCONNECTED); + break; + } +} + + + + + +/* Protocol Specific Packet Aliasing Routines + + IcmpAliasIn(), IcmpAliasIn1(), IcmpAliasIn2(), IcmpAliasIn3() + IcmpAliasOut(), IcmpAliasOut1(), IcmpAliasOut2(), IcmpAliasOut3() + UdpAliasIn(), UdpAliasOut() + TcpAliasIn(), TcpAliasOut() + +These routines handle protocol specific details of packet aliasing. +One may observe a certain amount of repetitive arithmetic in these +functions, the purpose of which is to compute a revised checksum +without actually summing over the entire data packet, which could be +unnecessarily time consuming. + +The purpose of the packet aliasing routines is to replace the source +address of the outgoing packet and then correctly put it back for +any incoming packets. For TCP and UDP, ports are also re-mapped. + +For ICMP echo/timestamp requests and replies, the following scheme +is used: the id number is replaced by an alias for the outgoing +packet. + +ICMP error messages are handled by looking at the IP fragment +in the data section of the message. + +For TCP and UDP protocols, a port number is chosen for an outgoing +packet, and then incoming packets are identified by IP address and +port numbers. For TCP packets, there is additional logic in the event +that sequence and ack numbers have been altered (as is the case for +FTP data port commands). + +The port numbers used by the packet aliasing module are not true +ports in the Unix sense. No sockets are actually bound to ports. +They are more correctly thought of as placeholders. + +All packets go through the aliasing mechanism, whether they come from +the gateway machine or other machines on a local area network. +*/ + + +/* Local prototypes */ +static int IcmpAliasIn1(struct ip *); +static int IcmpAliasIn2(struct ip *); +static int IcmpAliasIn3(struct ip *); +static int IcmpAliasIn (struct ip *); + +static int IcmpAliasOut1(struct ip *); +static int IcmpAliasOut2(struct ip *); +static int IcmpAliasOut3(struct ip *); +static int IcmpAliasOut (struct ip *); + +static int UdpAliasOut(struct ip *); +static int UdpAliasIn (struct ip *); + +static int TcpAliasOut(struct ip *, int); +static int TcpAliasIn (struct ip *); + + +static int +IcmpAliasIn1(struct ip *pip) +{ +/* + De-alias incoming echo and timestamp replies +*/ + struct alias_link *link; + struct icmp *ic; + + ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); + +/* Get source address from ICMP data field and restore original data */ + link = FindIcmpIn(pip->ip_src, pip->ip_dst, ic->icmp_id); + if (link != NULL) + { + u_short original_id; + int accumulate; + + original_id = GetOriginalPort(link); + +/* Adjust ICMP checksum */ + accumulate = ic->icmp_id; + accumulate -= original_id; + ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) + +/* Put original sequence number back in */ + ic->icmp_id = original_id; + +/* Put original address back into IP header */ + { + struct in_addr original_address; + + original_address = GetOriginalAddress(link); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &original_address, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = original_address; + } + + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + +static int +IcmpAliasIn2(struct ip *pip) +{ +/* + Alias incoming ICMP error messages containing + IP header and first 64 bits of datagram. +*/ + struct ip *ip; + struct icmp *ic, *ic2; + struct udphdr *ud; + struct tcphdr *tc; + struct alias_link *link; + + ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); + ip = (struct ip *) ic->icmp_data; + + ud = (struct udphdr *) ((char *) ip + (ip->ip_hl <<2)); + tc = (struct tcphdr *) ud; + ic2 = (struct icmp *) ud; + + if (ip->ip_p == IPPROTO_UDP) + link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, + ud->uh_dport, ud->uh_sport, + IPPROTO_UDP); + else if (ip->ip_p == IPPROTO_TCP) + link = FindUdpTcpIn(ip->ip_dst, ip->ip_src, + tc->th_dport, tc->th_sport, + IPPROTO_TCP); + else if (ip->ip_p == IPPROTO_ICMP) { + if (ic2->icmp_type == ICMP_ECHO || ic2->icmp_type == ICMP_TSTAMP) + link = FindIcmpIn(ip->ip_dst, ip->ip_src, ic2->icmp_id); + else + link = NULL; + } else + link = NULL; + + if (link != NULL) + { + if (ip->ip_p == IPPROTO_UDP || ip->ip_p == IPPROTO_TCP) + { + u_short *sptr; + int accumulate; + struct in_addr original_address; + u_short original_port; + + original_address = GetOriginalAddress(link); + original_port = GetOriginalPort(link); + +/* Adjust ICMP checksum */ + sptr = (u_short *) &(ip->ip_src); + accumulate = *sptr++; + accumulate += *sptr; + sptr = (u_short *) &original_address; + accumulate -= *sptr++; + accumulate -= *sptr; + accumulate += ud->uh_sport; + accumulate -= original_port; + ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) + +/* Un-alias address in IP header */ + DifferentialChecksum(&pip->ip_sum, + (u_short *) &original_address, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = original_address; + +/* Un-alias address and port number of original IP packet +fragment contained in ICMP data section */ + ip->ip_src = original_address; + ud->uh_sport = original_port; + } + else if (pip->ip_p == IPPROTO_ICMP) + { + u_short *sptr; + int accumulate; + struct in_addr original_address; + u_short original_id; + + original_address = GetOriginalAddress(link); + original_id = GetOriginalPort(link); + +/* Adjust ICMP checksum */ + sptr = (u_short *) &(ip->ip_src); + accumulate = *sptr++; + accumulate += *sptr; + sptr = (u_short *) &original_address; + accumulate -= *sptr++; + accumulate -= *sptr; + accumulate += ic2->icmp_id; + accumulate -= original_id; + ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) + +/* Un-alias address in IP header */ + DifferentialChecksum(&pip->ip_sum, + (u_short *) &original_address, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = original_address; + +/* Un-alias address of original IP packet and seqence number of + embedded icmp datagram */ + ip->ip_src = original_address; + ic2->icmp_id = original_id; + } + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + +static int +IcmpAliasIn3(struct ip *pip) +{ + struct in_addr original_address; + + original_address = FindOriginalAddress(pip->ip_dst); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &original_address, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = original_address; + + return PKT_ALIAS_OK; +} + + +static int +IcmpAliasIn(struct ip *pip) +{ + int iresult; + struct icmp *ic; + +/* Return if proxy-only mode is enabled */ + if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) + return PKT_ALIAS_OK; + + ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); + + iresult = PKT_ALIAS_IGNORED; + switch (ic->icmp_type) + { + case ICMP_ECHOREPLY: + case ICMP_TSTAMPREPLY: + if (ic->icmp_code == 0) + { + iresult = IcmpAliasIn1(pip); + } + break; + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + iresult = IcmpAliasIn2(pip); + break; + case ICMP_ECHO: + case ICMP_TSTAMP: + iresult = IcmpAliasIn3(pip); + break; + } + return(iresult); +} + + +static int +IcmpAliasOut1(struct ip *pip) +{ +/* + Alias ICMP echo and timestamp packets +*/ + struct alias_link *link; + struct icmp *ic; + + ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); + +/* Save overwritten data for when echo packet returns */ + link = FindIcmpOut(pip->ip_src, pip->ip_dst, ic->icmp_id); + if (link != NULL) + { + u_short alias_id; + int accumulate; + + alias_id = GetAliasPort(link); + +/* Since data field is being modified, adjust ICMP checksum */ + accumulate = ic->icmp_id; + accumulate -= alias_id; + ADJUST_CHECKSUM(accumulate, ic->icmp_cksum) + +/* Alias sequence number */ + ic->icmp_id = alias_id; + +/* Change source address */ + { + struct in_addr alias_address; + + alias_address = GetAliasAddress(link); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_address, + (u_short *) &pip->ip_src, + 2); + pip->ip_src = alias_address; + } + + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + + +static int +IcmpAliasOut2(struct ip *pip) +{ +/* + Alias outgoing ICMP error messages containing + IP header and first 64 bits of datagram. +*/ + struct in_addr alias_addr; + struct ip *ip; + struct icmp *ic; + + ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); + ip = (struct ip *) ic->icmp_data; + + alias_addr = FindAliasAddress(ip->ip_src); + +/* Alias destination address in IP fragment */ + DifferentialChecksum(&ic->icmp_cksum, + (u_short *) &alias_addr, + (u_short *) &ip->ip_dst, + 2); + ip->ip_dst = alias_addr; + +/* alias source address in IP header */ + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_addr, + (u_short *) &pip->ip_src, + 2); + pip->ip_src = alias_addr; + + return PKT_ALIAS_OK; +} + + +static int +IcmpAliasOut3(struct ip *pip) +{ +/* + Handle outgoing echo and timestamp replies. The + only thing which is done in this case is to alias + the source IP address of the packet. +*/ + struct in_addr alias_addr; + + alias_addr = FindAliasAddress(pip->ip_src); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_addr, + (u_short *) &pip->ip_src, + 2); + pip->ip_src = alias_addr; + + return PKT_ALIAS_OK; +} + + +static int +IcmpAliasOut(struct ip *pip) +{ + int iresult; + struct icmp *ic; + +/* Return if proxy-only mode is enabled */ + if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) + return PKT_ALIAS_OK; + + ic = (struct icmp *) ((char *) pip + (pip->ip_hl << 2)); + + iresult = PKT_ALIAS_IGNORED; + switch (ic->icmp_type) + { + case ICMP_ECHO: + case ICMP_TSTAMP: + if (ic->icmp_code == 0) + { + iresult = IcmpAliasOut1(pip); + } + break; + case ICMP_UNREACH: + case ICMP_SOURCEQUENCH: + case ICMP_TIMXCEED: + case ICMP_PARAMPROB: + iresult = IcmpAliasOut2(pip); + break; + case ICMP_ECHOREPLY: + case ICMP_TSTAMPREPLY: + iresult = IcmpAliasOut3(pip); + } + return(iresult); +} + + + +static int +PptpAliasIn(struct ip *pip) +{ +/* + Handle incoming PPTP packets. The + only thing which is done in this case is to alias + the dest IP address of the packet to our inside + machine. +*/ + struct in_addr alias_addr; + + if (!GetPptpAlias (&alias_addr)) + return PKT_ALIAS_IGNORED; + + if (pip->ip_src.s_addr != alias_addr.s_addr) { + + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_addr, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = alias_addr; + } + + return PKT_ALIAS_OK; +} + + +static int +PptpAliasOut(struct ip *pip) +{ +/* + Handle outgoing PPTP packets. The + only thing which is done in this case is to alias + the source IP address of the packet. +*/ + struct in_addr alias_addr; + + if (!GetPptpAlias (&alias_addr)) + return PKT_ALIAS_IGNORED; + + if (pip->ip_src.s_addr == alias_addr.s_addr) { + + alias_addr = FindAliasAddress(pip->ip_src); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_addr, + (u_short *) &pip->ip_src, + 2); + pip->ip_src = alias_addr; + } + + return PKT_ALIAS_OK; +} + + + +static int +UdpAliasIn(struct ip *pip) +{ + struct udphdr *ud; + struct alias_link *link; + +/* Return if proxy-only mode is enabled */ + if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) + return PKT_ALIAS_OK; + + ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); + + link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, + ud->uh_sport, ud->uh_dport, + IPPROTO_UDP); + if (link != NULL) + { + struct in_addr alias_address; + struct in_addr original_address; + u_short alias_port; + int accumulate; + u_short *sptr; + int r = 0; + + alias_address = GetAliasAddress(link); + original_address = GetOriginalAddress(link); + alias_port = ud->uh_dport; + ud->uh_dport = GetOriginalPort(link); + +/* If NETBIOS Datagram, It should be alias address in UDP Data, too */ + if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER + || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) + { + r = AliasHandleUdpNbt(pip, link, &original_address, ud->uh_dport); + } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER + || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) + { + r = AliasHandleUdpNbtNS(pip, link, + &alias_address, + &alias_port, + &original_address, + &ud->uh_dport ); + } + + if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) + AliasHandleCUSeeMeIn(pip, original_address); + +/* If UDP checksum is not zero, then adjust since destination port */ +/* is being unaliased and destination port is being altered. */ + if (ud->uh_sum != 0) + { + accumulate = alias_port; + accumulate -= ud->uh_dport; + sptr = (u_short *) &alias_address; + accumulate += *sptr++; + accumulate += *sptr; + sptr = (u_short *) &original_address; + accumulate -= *sptr++; + accumulate -= *sptr; + ADJUST_CHECKSUM(accumulate, ud->uh_sum) + } + +/* Restore original IP address */ + DifferentialChecksum(&pip->ip_sum, + (u_short *) &original_address, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = original_address; + + /* + * If we cannot figure out the packet, ignore it. + */ + if (r < 0) + return(PKT_ALIAS_IGNORED); + else + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + +static int +UdpAliasOut(struct ip *pip) +{ + struct udphdr *ud; + struct alias_link *link; + +/* Return if proxy-only mode is enabled */ + if (packetAliasMode & PKT_ALIAS_PROXY_ONLY) + return PKT_ALIAS_OK; + + ud = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); + + link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, + ud->uh_sport, ud->uh_dport, + IPPROTO_UDP); + if (link != NULL) + { + u_short alias_port; + struct in_addr alias_address; + + alias_address = GetAliasAddress(link); + alias_port = GetAliasPort(link); + + if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER) + AliasHandleCUSeeMeOut(pip, link); + +/* If NETBIOS Datagram, It should be alias address in UDP Data, too */ + if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER + || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER ) + { + AliasHandleUdpNbt(pip, link, &alias_address, alias_port); + } else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER + || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER ) + { + AliasHandleUdpNbtNS(pip, link, + &pip->ip_src, + &ud->uh_sport, + &alias_address, + &alias_port); + } + +/* If UDP checksum is not zero, adjust since source port is */ +/* being aliased and source address is being altered */ + if (ud->uh_sum != 0) + { + int accumulate; + u_short *sptr; + + accumulate = ud->uh_sport; + accumulate -= alias_port; + sptr = (u_short *) &(pip->ip_src); + accumulate += *sptr++; + accumulate += *sptr; + sptr = (u_short *) &alias_address; + accumulate -= *sptr++; + accumulate -= *sptr; + ADJUST_CHECKSUM(accumulate, ud->uh_sum) + } + +/* Put alias port in UDP header */ + ud->uh_sport = alias_port; + +/* Change source address */ + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_address, + (u_short *) &pip->ip_src, + 2); + pip->ip_src = alias_address; + + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + + + +static int +TcpAliasIn(struct ip *pip) +{ + struct tcphdr *tc; + struct alias_link *link; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + + link = FindUdpTcpIn(pip->ip_src, pip->ip_dst, + tc->th_sport, tc->th_dport, + IPPROTO_TCP); + if (link != NULL) + { + struct in_addr alias_address; + struct in_addr original_address; + struct in_addr proxy_address; + u_short alias_port; + u_short proxy_port; + int accumulate; + u_short *sptr; + + alias_address = GetAliasAddress(link); + original_address = GetOriginalAddress(link); + proxy_address = GetProxyAddress(link); + alias_port = tc->th_dport; + tc->th_dport = GetOriginalPort(link); + proxy_port = GetProxyPort(link); + +/* Adjust TCP checksum since destination port is being unaliased */ +/* and destination port is being altered. */ + accumulate = alias_port; + accumulate -= tc->th_dport; + sptr = (u_short *) &alias_address; + accumulate += *sptr++; + accumulate += *sptr; + sptr = (u_short *) &original_address; + accumulate -= *sptr++; + accumulate -= *sptr; + +/* If this is a proxy, then modify the tcp source port and + checksum accumulation */ + if (proxy_port != 0) + { + accumulate += tc->th_sport; + tc->th_sport = proxy_port; + accumulate -= tc->th_sport; + + sptr = (u_short *) &pip->ip_src; + accumulate += *sptr++; + accumulate += *sptr; + sptr = (u_short *) &proxy_address; + accumulate -= *sptr++; + accumulate -= *sptr; + } + +/* See if ack number needs to be modified */ + if (GetAckModified(link) == 1) + { + int delta; + + delta = GetDeltaAckIn(pip, link); + if (delta != 0) + { + sptr = (u_short *) &tc->th_ack; + accumulate += *sptr++; + accumulate += *sptr; + tc->th_ack = htonl(ntohl(tc->th_ack) - delta); + sptr = (u_short *) &tc->th_ack; + accumulate -= *sptr++; + accumulate -= *sptr; + } + } + + ADJUST_CHECKSUM(accumulate, tc->th_sum); + +/* Restore original IP address */ + sptr = (u_short *) &pip->ip_dst; + accumulate = *sptr++; + accumulate += *sptr; + pip->ip_dst = original_address; + sptr = (u_short *) &pip->ip_dst; + accumulate -= *sptr++; + accumulate -= *sptr; + +/* If this is a transparent proxy packet, then modify the source + address */ + if (proxy_address.s_addr != 0) + { + sptr = (u_short *) &pip->ip_src; + accumulate += *sptr++; + accumulate += *sptr; + pip->ip_src = proxy_address; + sptr = (u_short *) &pip->ip_src; + accumulate -= *sptr++; + accumulate -= *sptr; + } + + ADJUST_CHECKSUM(accumulate, pip->ip_sum); + +/* Monitor TCP connection state */ + TcpMonitorIn(pip, link); + + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + +static int +TcpAliasOut(struct ip *pip, int maxpacketsize) +{ + int proxy_type; + u_short dest_port; + u_short proxy_server_port; + struct in_addr dest_address; + struct in_addr proxy_server_address; + struct tcphdr *tc; + struct alias_link *link; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + + proxy_type = ProxyCheck(pip, &proxy_server_address, &proxy_server_port); + + if (proxy_type == 0 && (packetAliasMode & PKT_ALIAS_PROXY_ONLY)) + return PKT_ALIAS_OK; + +/* If this is a transparent proxy, save original destination, + then alter the destination and adust checksums */ + dest_port = tc->th_dport; + dest_address = pip->ip_dst; + if (proxy_type != 0) + { + int accumulate; + u_short *sptr; + + accumulate = tc->th_dport; + tc->th_dport = proxy_server_port; + accumulate -= tc->th_dport; + + sptr = (u_short *) &(pip->ip_dst); + accumulate += *sptr++; + accumulate += *sptr; + sptr = (u_short *) &proxy_server_address; + accumulate -= *sptr++; + accumulate -= *sptr; + + ADJUST_CHECKSUM(accumulate, tc->th_sum); + + sptr = (u_short *) &(pip->ip_dst); + accumulate = *sptr++; + accumulate += *sptr; + pip->ip_dst = proxy_server_address; + sptr = (u_short *) &(pip->ip_dst); + accumulate -= *sptr++; + accumulate -= *sptr; + + ADJUST_CHECKSUM(accumulate, pip->ip_sum); + } + + link = FindUdpTcpOut(pip->ip_src, pip->ip_dst, + tc->th_sport, tc->th_dport, + IPPROTO_TCP); + if (link !=NULL) + { + u_short alias_port; + struct in_addr alias_address; + int accumulate; + u_short *sptr; + +/* Save original destination address, if this is a proxy packet. + Also modify packet to include destination encoding. */ + if (proxy_type != 0) + { + SetProxyPort(link, dest_port); + SetProxyAddress(link, dest_address); + ProxyModify(link, pip, maxpacketsize, proxy_type); + } + +/* Get alias address and port */ + alias_port = GetAliasPort(link); + alias_address = GetAliasAddress(link); + +/* Monitor tcp connection state */ + TcpMonitorOut(pip, link); + +/* Special processing for IP encoding protocols */ + if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER + || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER) + AliasHandleFtpOut(pip, link, maxpacketsize); + if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1 + || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2) + AliasHandleIrcOut(pip, link, maxpacketsize); + +/* Adjust TCP checksum since source port is being aliased */ +/* and source address is being altered */ + accumulate = tc->th_sport; + tc->th_sport = alias_port; + accumulate -= tc->th_sport; + + sptr = (u_short *) &(pip->ip_src); + accumulate += *sptr++; + accumulate += *sptr; + sptr = (u_short *) &alias_address; + accumulate -= *sptr++; + accumulate -= *sptr; + +/* Modify sequence number if necessary */ + if (GetAckModified(link) == 1) + { + int delta; + + delta = GetDeltaSeqOut(pip, link); + if (delta != 0) + { + sptr = (u_short *) &tc->th_seq; + accumulate += *sptr++; + accumulate += *sptr; + tc->th_seq = htonl(ntohl(tc->th_seq) + delta); + sptr = (u_short *) &tc->th_seq; + accumulate -= *sptr++; + accumulate -= *sptr; + } + } + + ADJUST_CHECKSUM(accumulate, tc->th_sum) + +/* Change source address */ + sptr = (u_short *) &(pip->ip_src); + accumulate = *sptr++; + accumulate += *sptr; + pip->ip_src = alias_address; + sptr = (u_short *) &(pip->ip_src); + accumulate -= *sptr++; + accumulate -= *sptr; + + ADJUST_CHECKSUM(accumulate, pip->ip_sum) + + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_IGNORED); +} + + + + +/* Fragment Handling + + FragmentIn() + FragmentOut() + +The packet aliasing module has a limited ability for handling IP +fragments. If the ICMP, TCP or UDP header is in the first fragment +received, then the id number of the IP packet is saved, and other +fragments are identified according to their ID number and IP address +they were sent from. Pointers to unresolved fragments can also be +saved and recalled when a header fragment is seen. +*/ + +/* Local prototypes */ +static int FragmentIn(struct ip *); +static int FragmentOut(struct ip *); + + +static int +FragmentIn(struct ip *pip) +{ + struct alias_link *link; + + link = FindFragmentIn2(pip->ip_src, pip->ip_dst, pip->ip_id); + if (link != NULL) + { + struct in_addr original_address; + + GetFragmentAddr(link, &original_address); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &original_address, + (u_short *) &pip->ip_dst, + 2); + pip->ip_dst = original_address; + + return(PKT_ALIAS_OK); + } + return(PKT_ALIAS_UNRESOLVED_FRAGMENT); +} + + +static int +FragmentOut(struct ip *pip) +{ + struct in_addr alias_address; + + alias_address = FindAliasAddress(pip->ip_src); + DifferentialChecksum(&pip->ip_sum, + (u_short *) &alias_address, + (u_short *) &pip->ip_src, + 2); + pip->ip_src = alias_address; + + return(PKT_ALIAS_OK); +} + + + + + + +/* Outside World Access + + PacketAliasSaveFragment() + PacketAliasGetFragment() + PacketAliasFragmentIn() + PacketAliasIn() + PacketAliasOut() + +(prototypes in alias.h) +*/ + + +int +PacketAliasSaveFragment(char *ptr) +{ + int iresult; + struct alias_link *link; + struct ip *pip; + + pip = (struct ip *) ptr; + link = AddFragmentPtrLink(pip->ip_src, pip->ip_id); + iresult = PKT_ALIAS_ERROR; + if (link != NULL) + { + SetFragmentPtr(link, ptr); + iresult = PKT_ALIAS_OK; + } + return(iresult); +} + + +char * +PacketAliasGetFragment(char *ptr) +{ + struct alias_link *link; + char *fptr; + struct ip *pip; + + pip = (struct ip *) ptr; + link = FindFragmentPtr(pip->ip_src, pip->ip_id); + if (link != NULL) + { + GetFragmentPtr(link, &fptr); + SetFragmentPtr(link, NULL); + SetExpire(link, 0); /* Deletes link */ + + return(fptr); + } + else + { + return(NULL); + } +} + + +void +PacketAliasFragmentIn(char *ptr, /* Points to correctly de-aliased + header fragment */ + char *ptr_fragment /* Points to fragment which must + be de-aliased */ + ) +{ + struct ip *pip; + struct ip *fpip; + + pip = (struct ip *) ptr; + fpip = (struct ip *) ptr_fragment; + + DifferentialChecksum(&fpip->ip_sum, + (u_short *) &pip->ip_dst, + (u_short *) &fpip->ip_dst, + 2); + fpip->ip_dst = pip->ip_dst; +} + + +int +PacketAliasIn(char *ptr, int maxpacketsize) +{ + struct in_addr alias_addr; + struct ip *pip; + int iresult; + + if (packetAliasMode & PKT_ALIAS_REVERSE) + return PacketAliasOut(ptr, maxpacketsize); + + HouseKeeping(); + ClearCheckNewLink(); + pip = (struct ip *) ptr; + alias_addr = pip->ip_dst; + + /* Defense against mangled packets */ + if (ntohs(pip->ip_len) > maxpacketsize + || (pip->ip_hl<<2) > maxpacketsize) + return PKT_ALIAS_IGNORED; + + iresult = PKT_ALIAS_IGNORED; + if ( (ntohs(pip->ip_off) & IP_OFFMASK) == 0 ) + { + switch (pip->ip_p) + { + case IPPROTO_ICMP: + iresult = IcmpAliasIn(pip); + break; + case IPPROTO_UDP: + iresult = UdpAliasIn(pip); + break; + case IPPROTO_TCP: + iresult = TcpAliasIn(pip); + break; + case IPPROTO_GRE: + iresult = PptpAliasIn(pip); + break; + } + + if (ntohs(pip->ip_off) & IP_MF) + { + struct alias_link *link; + + link = FindFragmentIn1(pip->ip_src, alias_addr, pip->ip_id); + if (link != NULL) + { + iresult = PKT_ALIAS_FOUND_HEADER_FRAGMENT; + SetFragmentAddr(link, pip->ip_dst); + } + else + { + iresult = PKT_ALIAS_ERROR; + } + } + } + else + { + iresult = FragmentIn(pip); + } + + return(iresult); +} + + + +/* Unregistered address ranges */ + +/* 10.0.0.0 -> 10.255.255.255 */ +#define UNREG_ADDR_A_LOWER 0x0a000000 +#define UNREG_ADDR_A_UPPER 0x0affffff + +/* 172.16.0.0 -> 172.31.255.255 */ +#define UNREG_ADDR_B_LOWER 0xac100000 +#define UNREG_ADDR_B_UPPER 0xac1fffff + +/* 192.168.0.0 -> 192.168.255.255 */ +#define UNREG_ADDR_C_LOWER 0xc0a80000 +#define UNREG_ADDR_C_UPPER 0xc0a8ffff + +int +PacketAliasOut(char *ptr, /* valid IP packet */ + int maxpacketsize /* How much the packet data may grow + (FTP and IRC inline changes) */ + ) +{ + int iresult; + struct in_addr addr_save; + struct ip *pip; + + if (packetAliasMode & PKT_ALIAS_REVERSE) + return PacketAliasIn(ptr, maxpacketsize); + + HouseKeeping(); + ClearCheckNewLink(); + pip = (struct ip *) ptr; + + /* Defense against mangled packets */ + if (ntohs(pip->ip_len) > maxpacketsize + || (pip->ip_hl<<2) > maxpacketsize) + return PKT_ALIAS_IGNORED; + + addr_save = GetDefaultAliasAddress(); + if (packetAliasMode & PKT_ALIAS_UNREGISTERED_ONLY) + { + unsigned int addr; + int iclass; + + iclass = 0; + addr = ntohl(pip->ip_src.s_addr); + if (addr >= UNREG_ADDR_C_LOWER && addr <= UNREG_ADDR_C_UPPER) + iclass = 3; + else if (addr >= UNREG_ADDR_B_LOWER && addr <= UNREG_ADDR_B_UPPER) + iclass = 2; + else if (addr >= UNREG_ADDR_A_LOWER && addr <= UNREG_ADDR_A_UPPER) + iclass = 1; + + if (iclass == 0) + { + SetDefaultAliasAddress(pip->ip_src); + } + } + + iresult = PKT_ALIAS_IGNORED; + if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) + { + switch (pip->ip_p) + { + case IPPROTO_ICMP: + iresult = IcmpAliasOut(pip); + break; + case IPPROTO_UDP: + iresult = UdpAliasOut(pip); + break; + case IPPROTO_TCP: + iresult = TcpAliasOut(pip, maxpacketsize); + break; + case IPPROTO_GRE: + iresult = PptpAliasOut(pip); + break; + } + } + else + { + iresult = FragmentOut(pip); + } + + SetDefaultAliasAddress(addr_save); + return(iresult); +} diff --git a/alias/alias.h b/alias/alias.h new file mode 100644 index 0000000..4e0391f --- /dev/null +++ b/alias/alias.h @@ -0,0 +1,166 @@ +/*lint -save -library Flexelint comment for external headers */ + +/* + Alias.h defines the outside world interfaces for the packet + aliasing software. + + This software is placed into the public domain with no restrictions + on its distribution. + + $Id: alias.h,v 1.1.1.1 2000/01/11 01:48:42 wsanchez Exp $ +*/ + + +#ifndef _ALIAS_H_ +#define _ALIAS_H_ + +#ifndef NULL +#define NULL 0 +#endif + +/* Alias link representative (incomplete struct) */ +struct alias_link; + +/* External interfaces (API) to packet aliasing engine */ + +/* Initialization and Control */ + extern void + PacketAliasInit(void); + + extern void + PacketAliasUninit(void); + + extern void + PacketAliasSetAddress(struct in_addr); + + extern unsigned int + PacketAliasSetMode(unsigned int, unsigned int); + +#ifndef NO_FW_PUNCH + extern void + PacketAliasSetFWBase(unsigned int, unsigned int); +#endif + +/* Packet Handling */ + extern int + PacketAliasIn(char *, int maxpacketsize); + + extern int + PacketAliasOut(char *, int maxpacketsize); + +/* Port and Address Redirection */ + extern struct alias_link * + PacketAliasRedirectPort(struct in_addr, u_short, + struct in_addr, u_short, + struct in_addr, u_short, + u_char); + + extern int + PacketAliasPptp(struct in_addr); + + + extern struct alias_link * + PacketAliasRedirectAddr(struct in_addr, + struct in_addr); + + extern void + PacketAliasRedirectDelete(struct alias_link *); + +/* Fragment Handling */ + extern int + PacketAliasSaveFragment(char *); + + extern char * + PacketAliasGetFragment(char *); + + extern void + PacketAliasFragmentIn(char *, char *); + +/* Miscellaneous Functions */ + extern void + PacketAliasSetTarget(struct in_addr addr); + + extern int + PacketAliasCheckNewLink(void); + + extern u_short + PacketAliasInternetChecksum(u_short *, int); + +/* Transparent Proxying */ + extern int + PacketAliasProxyRule(const char *); + + +/********************** Mode flags ********************/ +/* Set these flags using SetPacketAliasMode() */ + +/* If PKT_ALIAS_LOG is set, a message will be printed to + /var/log/alias.log every time a link is created or deleted. This + is useful for debugging */ +#define PKT_ALIAS_LOG 0x01 + +/* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g. + to ftp, telnet or web servers will be prevented by the aliasing + mechanism. */ +#define PKT_ALIAS_DENY_INCOMING 0x02 + +/* If PKT_ALIAS_SAME_PORTS is set, packets will be attempted sent from + the same port as they originated on. This allows eg rsh to work + *99% of the time*, but _not_ 100%. (It will be slightly flakey + instead of not working at all.) This mode bit is set by + PacketAliasInit(), so it is a default mode of operation. */ +#define PKT_ALIAS_SAME_PORTS 0x04 + +/* If PKT_ALIAS_USE_SOCKETS is set, then when partially specified + links (e.g. destination port and/or address is zero), the packet + aliasing engine will attempt to allocate a socket for the aliasing + port it chooses. This will avoid interference with the host + machine. Fully specified links do not require this. This bit + is set after a call to PacketAliasInit(), so it is a default + mode of operation.*/ +#define PKT_ALIAS_USE_SOCKETS 0x08 + +/* If PKT_ALIAS_UNREGISTERED_ONLY is set, then only packets with with + unregistered source addresses will be aliased (along with those + of the ppp host maching itself. Private addresses are those + in the following ranges: + 10.0.0.0 -> 10.255.255.255 + 172.16.0.0 -> 172.31.255.255 + 192.168.0.0 -> 192.168.255.255 */ +#define PKT_ALIAS_UNREGISTERED_ONLY 0x10 + +/* If PKT_ALIAS_RESET_ON_ADDR_CHANGE is set, then the table of dynamic + aliasing links will be reset whenever PacketAliasSetAddress() + changes the default aliasing address. If the default aliasing + address is left unchanged by this functions call, then the + table of dynamic aliasing links will be left intact. This + bit is set after a call to PacketAliasInit(). */ +#define PKT_ALIAS_RESET_ON_ADDR_CHANGE 0x20 + +#ifndef NO_FW_PUNCH +/* If PKT_ALIAS_PUNCH_FW is set, active FTP and IRC DCC connections + will create a 'hole' in the firewall to allow the transfers to + work. Where (IPFW "line-numbers") the hole is created is + controlled by PacketAliasSetFWBase(base, size). The hole will be + attached to that particular alias_link, so when the link goes away + so do the hole. */ +#define PKT_ALIAS_PUNCH_FW 0x40 +#endif + +/* If PKT_ALIAS_PROXY_ONLY is set, then NAT will be disabled and only + transparent proxying performed */ +#define PKT_ALIAS_PROXY_ONLY 0x40 + +/* If PKT_ALIAS_REVERSE is set, the actions of PacketAliasIn() + and PacketAliasOut() are reversed */ +#define PKT_ALIAS_REVERSE 0x80 + +/* Return Codes */ +#define PKT_ALIAS_ERROR -1 +#define PKT_ALIAS_OK 1 +#define PKT_ALIAS_IGNORED 2 +#define PKT_ALIAS_UNRESOLVED_FRAGMENT 3 +#define PKT_ALIAS_FOUND_HEADER_FRAGMENT 4 + +#endif +/*lint -restore */ diff --git a/alias/alias_cuseeme.c b/alias/alias_cuseeme.c new file mode 100644 index 0000000..a78f041 --- /dev/null +++ b/alias/alias_cuseeme.c @@ -0,0 +1,120 @@ +/*- + * Copyright (c) 1998 Brian Somers + * with the aid of code written by + * Junichi SATOH 1996, 1997. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: alias_cuseeme.c,v 1.1.1.1 2000/01/11 01:48:42 wsanchez Exp $ + */ + +#include +#include +#include +#include +#include + +#include "alias_local.h" + +/* CU-SeeMe Data Header */ +struct cu_header { + u_int16_t dest_family; + u_int16_t dest_port; + u_int32_t dest_addr; + int16_t family; + u_int16_t port; + u_int32_t addr; + u_int32_t seq; + u_int16_t msg; + u_int16_t data_type; + u_int16_t packet_len; +}; + +/* Open Continue Header */ +struct oc_header { + u_int16_t client_count; /* Number of client info structs */ + u_int32_t seq_no; + char user_name[20]; + char reserved[4]; /* flags, version stuff, etc */ +}; + +/* client info structures */ +struct client_info { + u_int32_t address; /* Client address */ + char reserved[8]; /* Flags, pruning bitfield, packet counts etc */ +}; + +void +AliasHandleCUSeeMeOut(struct ip *pip, struct alias_link *link) +{ + struct udphdr *ud; + + ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2)); + if(ud->uh_ulen >= sizeof(struct cu_header)) { + struct cu_header *cu; + struct alias_link *cu_link; + + cu = (struct cu_header *)(ud + 1); + if (cu->addr) + cu->addr = (u_int32_t)GetAliasAddress(link).s_addr; + + cu_link = FindUdpTcpOut(pip->ip_src, GetDestAddress(link), + ud->uh_dport, 0, IPPROTO_UDP); + +#ifndef NO_FW_PUNCH + if (cu_link) + PunchFWHole(cu_link); +#endif + } +} + +void +AliasHandleCUSeeMeIn(struct ip *pip, struct in_addr original_addr) +{ + struct in_addr alias_addr; + struct udphdr *ud; + struct cu_header *cu; + struct oc_header *oc; + struct client_info *ci; + char *end; + int i; + + alias_addr.s_addr = pip->ip_dst.s_addr; + ud = (struct udphdr *)((char *)pip + (pip->ip_hl << 2)); + cu = (struct cu_header *)(ud + 1); + oc = (struct oc_header *)(cu + 1); + ci = (struct client_info *)(oc + 1); + end = (char *)cu + ud->uh_ulen; + + if ((char *)oc <= end) { + if(cu->dest_addr) + cu->dest_addr = (u_int32_t)original_addr.s_addr; + if(ntohs(cu->data_type) == 101) + /* Find and change our address */ + for(i = 0; (char *)(ci + 1) <= end && i < oc->client_count; i++, ci++) + if(ci->address == (u_int32_t)alias_addr.s_addr) { + ci->address = (u_int32_t)original_addr.s_addr; + break; + } + } +} diff --git a/alias/alias_db.c b/alias/alias_db.c new file mode 100644 index 0000000..d01188e --- /dev/null +++ b/alias/alias_db.c @@ -0,0 +1,2330 @@ +/* -*- mode: c; tab-width: 8; c-basic-indent: 4; -*- + Alias_db.c encapsulates all data structures used for storing + packet aliasing data. Other parts of the aliasing software + access data through functions provided in this file. + + Data storage is based on the notion of a "link", which is + established for ICMP echo/reply packets, UDP datagrams and + TCP stream connections. A link stores the original source + and destination addresses. For UDP and TCP, it also stores + source and destination port numbers, as well as an alias + port number. Links are also used to store information about + fragments. + + There is a facility for sweeping through and deleting old + links as new packets are sent through. A simple timeout is + used for ICMP and UDP links. TCP links are left alone unless + there is an incomplete connection, in which case the link + can be deleted after a certain amount of time. + + + This software is placed into the public domain with no restrictions + on its distribution. + + Initial version: August, 1996 (cjm) + + Version 1.4: September 16, 1996 (cjm) + Facility for handling incoming links added. + + Version 1.6: September 18, 1996 (cjm) + ICMP data handling simplified. + + Version 1.7: January 9, 1997 (cjm) + Fragment handling simplified. + Saves pointers for unresolved fragments. + Permits links for unspecied remote ports + or unspecified remote addresses. + Fixed bug which did not properly zero port + table entries after a link was deleted. + Cleaned up some obsolete comments. + + Version 1.8: January 14, 1997 (cjm) + Fixed data type error in StartPoint(). + (This error did not exist prior to v1.7 + and was discovered and fixed by Ari Suutari) + + Version 1.9: February 1, 1997 + Optionally, connections initiated from packet aliasing host + machine will will not have their port number aliased unless it + conflicts with an aliasing port already being used. (cjm) + + All options earlier being #ifdef'ed now are available through + a new interface, SetPacketAliasMode(). This allow run time + control (which is now available in PPP+pktAlias through the + 'alias' keyword). (ee) + + Added ability to create an alias port without + either destination address or port specified. + port type = ALIAS_PORT_UNKNOWN_DEST_ALL (ee) + + Removed K&R style function headers + and general cleanup. (ee) + + Added packetAliasMode to replace compiler #defines's (ee) + + Allocates sockets for partially specified + ports if ALIAS_USE_SOCKETS defined. (cjm) + + Version 2.0: March, 1997 + SetAliasAddress() will now clean up alias links + if the aliasing address is changed. (cjm) + + PacketAliasPermanentLink() function added to support permanent + links. (J. Fortes suggested the need for this.) + Examples: + + (192.168.0.1, port 23) <-> alias port 6002, unknown dest addr/port + + (192.168.0.2, port 21) <-> alias port 3604, known dest addr + unknown dest port + + These permament links allow for incoming connections to + machines on the local network. They can be given with a + user-chosen amount of specificity, with increasing specificity + meaning more security. (cjm) + + Quite a bit of rework to the basic engine. The portTable[] + array, which kept track of which ports were in use was replaced + by a table/linked list structure. (cjm) + + SetExpire() function added. (cjm) + + DeleteLink() no longer frees memory association with a pointer + to a fragment (this bug was first recognized by E. Eklund in + v1.9). + + Version 2.1: May, 1997 (cjm) + Packet aliasing engine reworked so that it can handle + multiple external addresses rather than just a single + host address. + + PacketAliasRedirectPort() and PacketAliasRedirectAddr() + added to the API. The first function is a more generalized + version of PacketAliasPermanentLink(). The second function + implements static network address translation. + + See HISTORY file for additional revisions. +*/ + + +/* System include files */ +#include +#include +#include + +#include +#include +#include +#include + +/* BSD network include files */ +#include +#include +#include +#include +#include + +#include "alias.h" +#include "alias_local.h" + + + +/* + Constants (note: constants are also defined + near relevant functions or structs) +*/ + +/* Sizes of input and output link tables */ +#define LINK_TABLE_OUT_SIZE 101 +#define LINK_TABLE_IN_SIZE 4001 + +/* Parameters used for cleanup of expired links */ +#define ALIAS_CLEANUP_INTERVAL_SECS 60 +#define ALIAS_CLEANUP_MAX_SPOKES 30 + +/* Timouts (in seconds) for different link types) */ +#define ICMP_EXPIRE_TIME 60 +#define UDP_EXPIRE_TIME 60 +#define FRAGMENT_ID_EXPIRE_TIME 10 +#define FRAGMENT_PTR_EXPIRE_TIME 30 + +/* TCP link expire time for different cases */ +/* When the link has been used and closed - minimal grace time to + allow ACKs and potential re-connect in FTP (XXX - is this allowed?) */ +#ifndef TCP_EXPIRE_DEAD +# define TCP_EXPIRE_DEAD 10 +#endif + +/* When the link has been used and closed on one side - the other side + is allowed to still send data */ +#ifndef TCP_EXPIRE_SINGLEDEAD +# define TCP_EXPIRE_SINGLEDEAD 90 +#endif + +/* When the link isn't yet up */ +#ifndef TCP_EXPIRE_INITIAL +# define TCP_EXPIRE_INITIAL 300 +#endif + +/* When the link is up */ +#ifndef TCP_EXPIRE_CONNECTED +# define TCP_EXPIRE_CONNECTED 86400 +#endif + + +/* Dummy port number codes used for FindLinkIn/Out() and AddLink(). + These constants can be anything except zero, which indicates an + unknown port number. */ + +#define NO_DEST_PORT 1 +#define NO_SRC_PORT 1 + + + +/* Data Structures + + The fundamental data structure used in this program is + "struct alias_link". Whenever a TCP connection is made, + a UDP datagram is sent out, or an ICMP echo request is made, + a link record is made (if it has not already been created). + The link record is identified by the source address/port + and the destination address/port. In the case of an ICMP + echo request, the source port is treated as being equivalent + with the 16-bit id number of the ICMP packet. + + The link record also can store some auxiliary data. For + TCP connections that have had sequence and acknowledgment + modifications, data space is available to track these changes. + A state field is used to keep track in changes to the tcp + connection state. Id numbers of fragments can also be + stored in the auxiliary space. Pointers to unresolved + framgents can also be stored. + + The link records support two independent chainings. Lookup + tables for input and out tables hold the initial pointers + the link chains. On input, the lookup table indexes on alias + port and link type. On output, the lookup table indexes on + source addreess, destination address, source port, destination + port and link type. +*/ + +struct ack_data_record /* used to save changes to ack/seq numbers */ +{ + u_long ack_old; + u_long ack_new; + int delta; + int active; +}; + +struct tcp_state /* Information about tcp connection */ +{ + int in; /* State for outside -> inside */ + int out; /* State for inside -> outside */ + int index; /* Index to ack data array */ + int ack_modified; /* Indicates whether ack and seq numbers */ + /* been modified */ +}; + +#define N_LINK_TCP_DATA 3 /* Number of distinct ack number changes + saved for a modified TCP stream */ +struct tcp_dat +{ + struct tcp_state state; + struct ack_data_record ack[N_LINK_TCP_DATA]; + int fwhole; /* Which firewall record is used for this hole? */ +}; + +struct alias_link /* Main data structure */ +{ + struct in_addr src_addr; /* Address and port information */ + struct in_addr dst_addr; + struct in_addr alias_addr; + struct in_addr proxy_addr; + u_short src_port; + u_short dst_port; + u_short alias_port; + u_short proxy_port; + + int link_type; /* Type of link: tcp, udp, icmp, frag */ + +/* values for link_type */ +#define LINK_ICMP 1 +#define LINK_UDP 2 +#define LINK_TCP 3 +#define LINK_FRAGMENT_ID 4 +#define LINK_FRAGMENT_PTR 5 +#define LINK_ADDR 6 + + int flags; /* indicates special characteristics */ + +/* flag bits */ +#define LINK_UNKNOWN_DEST_PORT 0x01 +#define LINK_UNKNOWN_DEST_ADDR 0x02 +#define LINK_PERMANENT 0x04 +#define LINK_PARTIALLY_SPECIFIED 0x03 /* logical-or of first two bits */ +#define LINK_UNFIREWALLED 0x08 + + int timestamp; /* Time link was last accessed */ + int expire_time; /* Expire time for link */ + + int sockfd; /* socket descriptor */ + + u_int start_point_out; /* Index number in output lookup table */ + u_int start_point_in; + struct alias_link *next_out; /* Linked list pointers for input and */ + struct alias_link *last_out; /* output tables */ + struct alias_link *next_in; /* . */ + struct alias_link *last_in; /* . */ + + union /* Auxiliary data */ + { + char *frag_ptr; + struct in_addr frag_addr; + struct tcp_dat *tcp; + } data; +}; + + + + + +/* Global Variables + + The global variables listed here are only accessed from + within alias_db.c and so are prefixed with the static + designation. +*/ + +int packetAliasMode; /* Mode flags */ + /* - documented in alias.h */ + +static struct in_addr aliasAddress; /* Address written onto source */ + /* field of IP packet. */ + +static struct in_addr targetAddress; /* IP address incoming packets */ + /* are sent to if no aliasing */ + /* link already exists */ + +static struct in_addr nullAddress; /* Used as a dummy parameter for */ + /* some function calls */ +static struct alias_link * +linkTableOut[LINK_TABLE_OUT_SIZE]; /* Lookup table of pointers to */ + /* chains of link records. Each */ +static struct alias_link * /* link record is doubly indexed */ +linkTableIn[LINK_TABLE_IN_SIZE]; /* into input and output lookup */ + /* tables. */ + +static int icmpLinkCount; /* Link statistics */ +static int udpLinkCount; +static int tcpLinkCount; +static int fragmentIdLinkCount; +static int fragmentPtrLinkCount; +static int sockCount; + +static int cleanupIndex; /* Index to chain of link table */ + /* being inspected for old links */ + +static int timeStamp; /* System time in seconds for */ + /* current packet */ + +static int lastCleanupTime; /* Last time IncrementalCleanup() */ + /* was called */ + +static int houseKeepingResidual; /* used by HouseKeeping() */ + +static int deleteAllLinks; /* If equal to zero, DeleteLink() */ + /* will not remove permanent links */ + +static FILE *monitorFile; /* File descriptor for link */ + /* statistics monitoring file */ + +static int newDefaultLink; /* Indicates if a new aliasing */ + /* link has been created after a */ + /* call to PacketAliasIn/Out(). */ + +#ifndef NO_FW_PUNCH +static int fireWallFD = -1; /* File descriptor to be able to */ + /* control firewall. Opened by */ + /* PacketAliasSetMode on first */ + /* setting the PKT_ALIAS_PUNCH_FW */ + /* flag. */ +#endif + +static int pptpAliasFlag; /* Indicates if PPTP aliasing is */ + /* on or off */ +static struct in_addr pptpAliasAddr; /* Address of source of PPTP */ + /* packets. */ + + + + + + + +/* Internal utility routines (used only in alias_db.c) + +Lookup table starting points: + StartPointIn() -- link table initial search point for + outgoing packets + StartPointOut() -- port table initial search point for + incoming packets + +Miscellaneous: + SeqDiff() -- difference between two TCP sequences + ShowAliasStats() -- send alias statistics to a monitor file +*/ + + +/* Local prototypes */ +static u_int StartPointIn(struct in_addr, u_short, int); + +static u_int StartPointOut(struct in_addr, struct in_addr, + u_short, u_short, int); + +static int SeqDiff(u_long, u_long); + +static void ShowAliasStats(void); + +#ifndef NO_FW_PUNCH +/* Firewall control */ +static void InitPunchFW(void); +static void UninitPunchFW(void); +static void ClearFWHole(struct alias_link *link); +#endif + +/* Log file control */ +static void InitPacketAliasLog(void); +static void UninitPacketAliasLog(void); + +static u_int +StartPointIn(struct in_addr alias_addr, + u_short alias_port, + int link_type) +{ + u_int n; + + n = alias_addr.s_addr; + n += alias_port; + n += link_type; + return(n % LINK_TABLE_IN_SIZE); +} + + +static u_int +StartPointOut(struct in_addr src_addr, struct in_addr dst_addr, + u_short src_port, u_short dst_port, int link_type) +{ + u_int n; + + n = src_addr.s_addr; + n += dst_addr.s_addr; + n += src_port; + n += dst_port; + n += link_type; + + return(n % LINK_TABLE_OUT_SIZE); +} + + +static int +SeqDiff(u_long x, u_long y) +{ +/* Return the difference between two TCP sequence numbers */ + +/* + This function is encapsulated in case there are any unusual + arithmetic conditions that need to be considered. +*/ + + return (ntohl(y) - ntohl(x)); +} + + +static void +ShowAliasStats(void) +{ +/* Used for debugging */ + + if (monitorFile) + { + fprintf(monitorFile, "icmp=%d, udp=%d, tcp=%d, frag_id=%d frag_ptr=%d", + icmpLinkCount, + udpLinkCount, + tcpLinkCount, + fragmentIdLinkCount, + fragmentPtrLinkCount); + + fprintf(monitorFile, " / tot=%d (sock=%d)\n", + icmpLinkCount + udpLinkCount + + tcpLinkCount + + fragmentIdLinkCount + + fragmentPtrLinkCount, + sockCount); + + fflush(monitorFile); + } +} + + + + + +/* Internal routines for finding, deleting and adding links + +Port Allocation: + GetNewPort() -- find and reserve new alias port number + GetSocket() -- try to allocate a socket for a given port + +Link creation and deletion: + CleanupAliasData() - remove all link chains from lookup table + IncrementalCleanup() - look for stale links in a single chain + DeleteLink() - remove link + AddLink() - add link + ReLink() - change link + +Link search: + FindLinkOut() - find link for outgoing packets + FindLinkIn() - find link for incoming packets +*/ + +/* Local prototypes */ +static int GetNewPort(struct alias_link *, int); + +static u_short GetSocket(u_short, int *, int); + +static void CleanupAliasData(void); + +static void IncrementalCleanup(void); + +static void DeleteLink(struct alias_link *); + +static struct alias_link * +AddLink(struct in_addr, struct in_addr, struct in_addr, + u_short, u_short, int, int); + +static struct alias_link * +ReLink(struct alias_link *, + struct in_addr, struct in_addr, struct in_addr, + u_short, u_short, int, int); + +static struct alias_link * +FindLinkOut(struct in_addr, struct in_addr, u_short, u_short, int); + +static struct alias_link * +FindLinkIn(struct in_addr, struct in_addr, u_short, u_short, int, int); + + +#define ALIAS_PORT_BASE 0x08000 +#define ALIAS_PORT_MASK 0x07fff +#define GET_NEW_PORT_MAX_ATTEMPTS 20 + +#define GET_ALIAS_PORT -1 +#define GET_ALIAS_ID GET_ALIAS_PORT + +/* GetNewPort() allocates port numbers. Note that if a port number + is already in use, that does not mean that it cannot be used by + another link concurrently. This is because GetNewPort() looks for + unused triplets: (dest addr, dest port, alias port). */ + +static int +GetNewPort(struct alias_link *link, int alias_port_param) +{ + int i; + int max_trials; + u_short port_sys; + u_short port_net; + +/* + Description of alias_port_param for GetNewPort(). When + this parameter is zero or positive, it precisely specifies + the port number. GetNewPort() will return this number + without check that it is in use. + + Whis this parameter is -1, it indicates to get a randomly + selected port number. +*/ + + if (alias_port_param == GET_ALIAS_PORT) + { + /* + * The aliasing port is automatically selected + * by one of two methods below: + */ + max_trials = GET_NEW_PORT_MAX_ATTEMPTS; + + if (packetAliasMode & PKT_ALIAS_SAME_PORTS) + { + /* + * When the ALIAS_SAME_PORTS option is + * chosen, the first try will be the + * actual source port. If this is already + * in use, the remainder of the trials + * will be random. + */ + port_net = link->src_port; + port_sys = ntohs(port_net); + } + else + { + /* First trial and all subsequent are random. */ + port_sys = random() & ALIAS_PORT_MASK; + port_sys += ALIAS_PORT_BASE; + port_net = htons(port_sys); + } + } + else if (alias_port_param >= 0 && alias_port_param < 0x10000) + { + link->alias_port = (u_short) alias_port_param; + return(0); + } + else + { +#ifdef DEBUG + fprintf(stderr, "PacketAlias/GetNewPort(): "); + fprintf(stderr, "input parameter error\n"); +#endif + return(-1); + } + + +/* Port number search */ + for (i=0; idst_addr, link->alias_addr, + link->dst_port, port_net, + link->link_type, 0); + + if (search_result == NULL) + go_ahead = 1; + else if (!(link->flags & LINK_PARTIALLY_SPECIFIED) + && (search_result->flags & LINK_PARTIALLY_SPECIFIED)) + go_ahead = 1; + else + go_ahead = 0; + + if (go_ahead) + { + if ((packetAliasMode && PKT_ALIAS_USE_SOCKETS) + && (link->flags & LINK_PARTIALLY_SPECIFIED)) + { + if (GetSocket(port_net, &link->sockfd, link->link_type)) + { + link->alias_port = port_net; + return(0); + } + } + else + { + link->alias_port = port_net; + return(0); + } + } + + port_sys = random() & ALIAS_PORT_MASK; + port_sys += ALIAS_PORT_BASE; + port_net = htons(port_sys); + } + +#ifdef DEBUG + fprintf(stderr, "PacketAlias/GetnewPort(): "); + fprintf(stderr, "could not find free port\n"); +#endif + + return(-1); +} + + +static u_short +GetSocket(u_short port_net, int *sockfd, int link_type) +{ + int err; + int sock; + struct sockaddr_in sock_addr; + + if (link_type == LINK_TCP) + sock = socket(AF_INET, SOCK_STREAM, 0); + else if (link_type == LINK_UDP) + sock = socket(AF_INET, SOCK_DGRAM, 0); + else + { +#ifdef DEBUG + fprintf(stderr, "PacketAlias/GetSocket(): "); + fprintf(stderr, "incorrect link type\n"); +#endif + return(0); + } + + if (sock < 0) + { +#ifdef DEBUG + fprintf(stderr, "PacketAlias/GetSocket(): "); + fprintf(stderr, "socket() error %d\n", *sockfd); +#endif + return(0); + } + + sock_addr.sin_family = AF_INET; + sock_addr.sin_addr.s_addr = htonl(INADDR_ANY); + sock_addr.sin_port = port_net; + + err = bind(sock, + (struct sockaddr *) &sock_addr, + sizeof(sock_addr)); + if (err == 0) + { + sockCount++; + *sockfd = sock; + return(1); + } + else + { + close(sock); + return(0); + } +} + + +static void +CleanupAliasData(void) +{ + struct alias_link *link; + int i, icount; + + icount = 0; + for (i=0; inext_out; + icount++; + DeleteLink(link); + link = link_next; + } + } + + cleanupIndex =0; +} + + +static void +IncrementalCleanup(void) +{ + int icount; + struct alias_link *link; + + icount = 0; + link = linkTableOut[cleanupIndex++]; + while (link != NULL) + { + int idelta; + struct alias_link *link_next; + + link_next = link->next_out; + idelta = timeStamp - link->timestamp; + switch (link->link_type) + { + case LINK_ICMP: + case LINK_UDP: + case LINK_FRAGMENT_ID: + case LINK_FRAGMENT_PTR: + if (idelta > link->expire_time) + { + DeleteLink(link); + icount++; + } + break; + case LINK_TCP: + if (idelta > link->expire_time) + { + struct tcp_dat *tcp_aux; + + tcp_aux = link->data.tcp; + if (tcp_aux->state.in != ALIAS_TCP_STATE_CONNECTED + || tcp_aux->state.out != ALIAS_TCP_STATE_CONNECTED) + { + DeleteLink(link); + icount++; + } + } + break; + } + link = link_next; + } + + if (cleanupIndex == LINK_TABLE_OUT_SIZE) + cleanupIndex = 0; +} + +void +DeleteLink(struct alias_link *link) +{ + struct alias_link *link_last; + struct alias_link *link_next; + +/* Don't do anything if the link is marked permanent */ + if (deleteAllLinks == 0 && link->flags & LINK_PERMANENT) + return; + +#ifndef NO_FW_PUNCH +/* Delete associatied firewall hole, if any */ + ClearFWHole(link); +#endif + +/* Adjust output table pointers */ + link_last = link->last_out; + link_next = link->next_out; + + if (link_last != NULL) + link_last->next_out = link_next; + else + linkTableOut[link->start_point_out] = link_next; + + if (link_next != NULL) + link_next->last_out = link_last; + +/* Adjust input table pointers */ + link_last = link->last_in; + link_next = link->next_in; + + if (link_last != NULL) + link_last->next_in = link_next; + else + linkTableIn[link->start_point_in] = link_next; + + if (link_next != NULL) + link_next->last_in = link_last; + +/* Close socket, if one has been allocated */ + if (link->sockfd != -1) + { + sockCount--; + close(link->sockfd); + } + +/* Link-type dependent cleanup */ + switch(link->link_type) + { + case LINK_ICMP: + icmpLinkCount--; + break; + case LINK_UDP: + udpLinkCount--; + break; + case LINK_TCP: + tcpLinkCount--; + if (link->data.tcp != NULL) + free(link->data.tcp); + break; + case LINK_FRAGMENT_ID: + fragmentIdLinkCount--; + break; + case LINK_FRAGMENT_PTR: + fragmentPtrLinkCount--; + if (link->data.frag_ptr != NULL) + free(link->data.frag_ptr); + break; + } + +/* Free memory */ + free(link); + +/* Write statistics, if logging enabled */ + if (packetAliasMode & PKT_ALIAS_LOG) + { + ShowAliasStats(); + } +} + + +static struct alias_link * +AddLink(struct in_addr src_addr, + struct in_addr dst_addr, + struct in_addr alias_addr, + u_short src_port, + u_short dst_port, + int alias_port_param, /* if less than zero, alias */ + int link_type) /* port will be automatically */ +{ /* chosen. If greater than */ + u_int start_point; /* zero, equal to alias port */ + struct alias_link *link; + struct alias_link *first_link; + + link = malloc(sizeof(struct alias_link)); + if (link != NULL) + { + /* If either the aliasing address or source address are + equal to the default device address (equal to the + global variable aliasAddress), then set the alias + address field of the link record to zero */ + + if (src_addr.s_addr == aliasAddress.s_addr) + src_addr.s_addr = 0; + + if (alias_addr.s_addr == aliasAddress.s_addr) + alias_addr.s_addr = 0; + + /* Basic initialization */ + link->src_addr = src_addr; + link->dst_addr = dst_addr; + link->alias_addr = alias_addr; + link->proxy_addr.s_addr = 0; + link->src_port = src_port; + link->dst_port = dst_port; + link->proxy_port = 0; + link->link_type = link_type; + link->sockfd = -1; + link->flags = 0; + link->timestamp = timeStamp; + + /* Expiration time */ + switch (link_type) + { + case LINK_ICMP: + link->expire_time = ICMP_EXPIRE_TIME; + break; + case LINK_UDP: + link->expire_time = UDP_EXPIRE_TIME; + break; + case LINK_TCP: + link->expire_time = TCP_EXPIRE_INITIAL; + break; + case LINK_FRAGMENT_ID: + link->expire_time = FRAGMENT_ID_EXPIRE_TIME; + break; + case LINK_FRAGMENT_PTR: + link->expire_time = FRAGMENT_PTR_EXPIRE_TIME; + break; + } + + /* Determine alias flags */ + if (dst_addr.s_addr == 0) + link->flags |= LINK_UNKNOWN_DEST_ADDR; + if (dst_port == 0) + link->flags |= LINK_UNKNOWN_DEST_PORT; + + /* Determine alias port */ + if (GetNewPort(link, alias_port_param) != 0) + { + free(link); + return(NULL); + } + + /* Set up pointers for output lookup table */ + start_point = StartPointOut(src_addr, dst_addr, + src_port, dst_port, link_type); + first_link = linkTableOut[start_point]; + + link->last_out = NULL; + link->next_out = first_link; + link->start_point_out = start_point; + + if (first_link != NULL) + first_link->last_out = link; + + linkTableOut[start_point] = link; + + /* Set up pointers for input lookup table */ + start_point = StartPointIn(alias_addr, link->alias_port, link_type); + first_link = linkTableIn[start_point]; + + link->last_in = NULL; + link->next_in = first_link; + link->start_point_in = start_point; + + if (first_link != NULL) + first_link->last_in = link; + + linkTableIn[start_point] = link; + + /* Link-type dependent initialization */ + switch(link_type) + { + struct tcp_dat *aux_tcp; + + case LINK_ICMP: + icmpLinkCount++; + break; + case LINK_UDP: + udpLinkCount++; + break; + case LINK_TCP: + aux_tcp = malloc(sizeof(struct tcp_dat)); + link->data.tcp = aux_tcp; + if (aux_tcp != NULL) + { + int i; + + tcpLinkCount++; + aux_tcp->state.in = ALIAS_TCP_STATE_NOT_CONNECTED; + aux_tcp->state.out = ALIAS_TCP_STATE_NOT_CONNECTED; + aux_tcp->state.index = 0; + aux_tcp->state.ack_modified = 0; + for (i=0; iack[i].active = 0; + aux_tcp->fwhole = -1; + } + else + { +#ifdef DEBUG + fprintf(stderr, "PacketAlias/AddLink: "); + fprintf(stderr, " cannot allocate auxiliary TCP data\n"); +#endif + } + break; + case LINK_FRAGMENT_ID: + fragmentIdLinkCount++; + break; + case LINK_FRAGMENT_PTR: + fragmentPtrLinkCount++; + break; + } + } + else + { +#ifdef DEBUG + fprintf(stderr, "PacketAlias/AddLink(): "); + fprintf(stderr, "malloc() call failed.\n"); +#endif + } + + if (packetAliasMode & PKT_ALIAS_LOG) + { + ShowAliasStats(); + } + + return(link); +} + +static struct alias_link * +ReLink(struct alias_link *old_link, + struct in_addr src_addr, + struct in_addr dst_addr, + struct in_addr alias_addr, + u_short src_port, + u_short dst_port, + int alias_port_param, /* if less than zero, alias */ + int link_type) /* port will be automatically */ +{ /* chosen. If greater than */ + struct alias_link *new_link; /* zero, equal to alias port */ + + new_link = AddLink(src_addr, dst_addr, alias_addr, + src_port, dst_port, alias_port_param, + link_type); +#ifndef NO_FW_PUNCH + if (new_link != NULL && + old_link->link_type == LINK_TCP && + old_link->data.tcp && + old_link->data.tcp->fwhole > 0) { + PunchFWHole(new_link); + } +#endif + DeleteLink(old_link); + return new_link; +} + +static struct alias_link * +FindLinkOut(struct in_addr src_addr, + struct in_addr dst_addr, + u_short src_port, + u_short dst_port, + int link_type) +{ + u_int i; + struct alias_link *link; + + if (src_addr.s_addr == aliasAddress.s_addr) + src_addr.s_addr = 0; + + i = StartPointOut(src_addr, dst_addr, src_port, dst_port, link_type); + link = linkTableOut[i]; + while (link != NULL) + { + if (link->src_addr.s_addr == src_addr.s_addr + && link->dst_addr.s_addr == dst_addr.s_addr + && link->dst_port == dst_port + && link->src_port == src_port + && link->link_type == link_type) + { + link->timestamp = timeStamp; + break; + } + link = link->next_out; + } + + return(link); +} + + +struct alias_link * +FindLinkIn(struct in_addr dst_addr, + struct in_addr alias_addr, + u_short dst_port, + u_short alias_port, + int link_type, + int replace_partial_links) +{ + int flags_in; + u_int start_point; + struct alias_link *link; + struct alias_link *link_fully_specified; + struct alias_link *link_unknown_all; + struct alias_link *link_unknown_dst_addr; + struct alias_link *link_unknown_dst_port; + +/* Initialize pointers */ + link_fully_specified = NULL; + link_unknown_all = NULL; + link_unknown_dst_addr = NULL; + link_unknown_dst_port = NULL; + +/* If either the dest addr or port is unknown, the search + loop will have to know about this. */ + + flags_in = 0; + if (dst_addr.s_addr == 0) + flags_in |= LINK_UNKNOWN_DEST_ADDR; + if (dst_port == 0) + flags_in |= LINK_UNKNOWN_DEST_PORT; + +/* The following allows permanent links to be + be specified as using the default aliasing address + (i.e. device interface address) without knowing + in advance what that address is. */ + + if (alias_addr.s_addr == aliasAddress.s_addr) + alias_addr.s_addr = 0; + +/* Search loop */ + start_point = StartPointIn(alias_addr, alias_port, link_type); + link = linkTableIn[start_point]; + while (link != NULL) + { + int flags; + + flags = flags_in | link->flags; + if (!(flags & LINK_PARTIALLY_SPECIFIED)) + { + if (link->alias_addr.s_addr == alias_addr.s_addr + && link->alias_port == alias_port + && link->dst_addr.s_addr == dst_addr.s_addr + && link->dst_port == dst_port + && link->link_type == link_type) + { + link_fully_specified = link; + break; + } + } + else if ((flags & LINK_UNKNOWN_DEST_ADDR) + && (flags & LINK_UNKNOWN_DEST_PORT)) + { + if (link->alias_addr.s_addr == alias_addr.s_addr + && link->alias_port == alias_port + && link->link_type == link_type) + { + if (link_unknown_all == NULL) + link_unknown_all = link; + } + } + else if (flags & LINK_UNKNOWN_DEST_ADDR) + { + if (link->alias_addr.s_addr == alias_addr.s_addr + && link->alias_port == alias_port + && link->link_type == link_type + && link->dst_port == dst_port) + { + if (link_unknown_dst_addr == NULL) + link_unknown_dst_addr = link; + } + } + else if (flags & LINK_UNKNOWN_DEST_PORT) + { + if (link->alias_addr.s_addr == alias_addr.s_addr + && link->alias_port == alias_port + && link->link_type == link_type + && link->dst_addr.s_addr == dst_addr.s_addr) + { + if (link_unknown_dst_port == NULL) + link_unknown_dst_port = link; + } + } + link = link->next_in; + } + + + + if (link_fully_specified != NULL) + { + return link_fully_specified; + } + else if (link_unknown_dst_port != NULL) + { + return replace_partial_links + ? ReLink(link_unknown_dst_port, + link_unknown_dst_port->src_addr, dst_addr, alias_addr, + link_unknown_dst_port->src_port, dst_port, alias_port, + link_type) + : link_unknown_dst_port; + } + else if (link_unknown_dst_addr != NULL) + { + return replace_partial_links + ? ReLink(link_unknown_dst_addr, + link_unknown_dst_addr->src_addr, dst_addr, alias_addr, + link_unknown_dst_addr->src_port, dst_port, alias_port, + link_type) + : link_unknown_dst_addr; + } + else if (link_unknown_all != NULL) + { + return replace_partial_links + ? ReLink(link_unknown_all, + link_unknown_all->src_addr, dst_addr, alias_addr, + link_unknown_all->src_port, dst_port, alias_port, + link_type) + : link_unknown_all; + } + else + { + return(NULL); + } +} + + + + +/* External routines for finding/adding links + +-- "external" means outside alias_db.c, but within alias*.c -- + + FindIcmpIn(), FindIcmpOut() + FindFragmentIn1(), FindFragmentIn2() + AddFragmentPtrLink(), FindFragmentPtr() + FindUdpTcpIn(), FindUdpTcpOut() + FindOriginalAddress(), FindAliasAddress() + +(prototypes in alias_local.h) +*/ + + +struct alias_link * +FindIcmpIn(struct in_addr dst_addr, + struct in_addr alias_addr, + u_short id_alias) +{ + return FindLinkIn(dst_addr, alias_addr, + NO_DEST_PORT, id_alias, + LINK_ICMP, 0); +} + + +struct alias_link * +FindIcmpOut(struct in_addr src_addr, + struct in_addr dst_addr, + u_short id) +{ + struct alias_link * link; + + link = FindLinkOut(src_addr, dst_addr, + id, NO_DEST_PORT, + LINK_ICMP); + if (link == NULL) + { + struct in_addr alias_addr; + + alias_addr = FindAliasAddress(src_addr); + link = AddLink(src_addr, dst_addr, alias_addr, + id, NO_DEST_PORT, GET_ALIAS_ID, + LINK_ICMP); + } + + return(link); +} + + +struct alias_link * +FindFragmentIn1(struct in_addr dst_addr, + struct in_addr alias_addr, + u_short ip_id) +{ + struct alias_link *link; + + link = FindLinkIn(dst_addr, alias_addr, + NO_DEST_PORT, ip_id, + LINK_FRAGMENT_ID, 0); + + if (link == NULL) + { + link = AddLink(nullAddress, dst_addr, alias_addr, + NO_SRC_PORT, NO_DEST_PORT, ip_id, + LINK_FRAGMENT_ID); + } + + return(link); +} + + +struct alias_link * +FindFragmentIn2(struct in_addr dst_addr, /* Doesn't add a link if one */ + struct in_addr alias_addr, /* is not found. */ + u_short ip_id) +{ + return FindLinkIn(dst_addr, alias_addr, + NO_DEST_PORT, ip_id, + LINK_FRAGMENT_ID, 0); +} + + +struct alias_link * +AddFragmentPtrLink(struct in_addr dst_addr, + u_short ip_id) +{ + return AddLink(nullAddress, dst_addr, nullAddress, + NO_SRC_PORT, NO_DEST_PORT, ip_id, + LINK_FRAGMENT_PTR); +} + + +struct alias_link * +FindFragmentPtr(struct in_addr dst_addr, + u_short ip_id) +{ + return FindLinkIn(dst_addr, nullAddress, + NO_DEST_PORT, ip_id, + LINK_FRAGMENT_PTR, 0); +} + + +struct alias_link * +FindUdpTcpIn(struct in_addr dst_addr, + struct in_addr alias_addr, + u_short dst_port, + u_short alias_port, + u_char proto) +{ + int link_type; + struct alias_link *link; + + switch (proto) + { + case IPPROTO_UDP: + link_type = LINK_UDP; + break; + case IPPROTO_TCP: + link_type = LINK_TCP; + break; + default: + return NULL; + break; + } + + link = FindLinkIn(dst_addr, alias_addr, + dst_port, alias_port, + link_type, 1); + + if (!(packetAliasMode & PKT_ALIAS_DENY_INCOMING) + && !(packetAliasMode & PKT_ALIAS_PROXY_ONLY) + && link == NULL) + { + struct in_addr target_addr; + + target_addr = FindOriginalAddress(alias_addr); + link = AddLink(target_addr, dst_addr, alias_addr, + alias_port, dst_port, alias_port, + link_type); + } + + return(link); +} + + +struct alias_link * +FindUdpTcpOut(struct in_addr src_addr, + struct in_addr dst_addr, + u_short src_port, + u_short dst_port, + u_char proto) +{ + int link_type; + struct alias_link *link; + + switch (proto) + { + case IPPROTO_UDP: + link_type = LINK_UDP; + break; + case IPPROTO_TCP: + link_type = LINK_TCP; + break; + default: + return NULL; + break; + } + + link = FindLinkOut(src_addr, dst_addr, src_port, dst_port, link_type); + + if (link == NULL) + { + struct in_addr alias_addr; + + alias_addr = FindAliasAddress(src_addr); + link = AddLink(src_addr, dst_addr, alias_addr, + src_port, dst_port, GET_ALIAS_PORT, + link_type); + } + + return(link); +} + + +struct in_addr +FindOriginalAddress(struct in_addr alias_addr) +{ + struct alias_link *link; + + link = FindLinkIn(nullAddress, alias_addr, + 0, 0, LINK_ADDR, 0); + if (link == NULL) + { + newDefaultLink = 1; + if (targetAddress.s_addr != 0) + return targetAddress; + else + return alias_addr; + } + else + { + if (link->src_addr.s_addr == 0) + return aliasAddress; + else + return link->src_addr; + } +} + + +struct in_addr +FindAliasAddress(struct in_addr original_addr) +{ + struct alias_link *link; + + link = FindLinkOut(original_addr, nullAddress, + 0, 0, LINK_ADDR); + if (link == NULL) + { + return aliasAddress; + } + else + { + if (link->alias_addr.s_addr == 0) + return aliasAddress; + else + return link->alias_addr; + } +} + + +/* External routines for getting or changing link data + (external to alias_db.c, but internal to alias*.c) + + SetFragmentData(), GetFragmentData() + SetFragmentPtr(), GetFragmentPtr() + SetStateIn(), SetStateOut(), GetStateIn(), GetStateOut() + GetOriginalAddress(), GetDestAddress(), GetAliasAddress() + GetOriginalPort(), GetAliasPort() + SetAckModified(), GetAckModified() + GetDeltaAckIn(), GetDeltaSeqOut(), AddSeq() +*/ + + +void +SetFragmentAddr(struct alias_link *link, struct in_addr src_addr) +{ + link->data.frag_addr = src_addr; +} + + +void +GetFragmentAddr(struct alias_link *link, struct in_addr *src_addr) +{ + *src_addr = link->data.frag_addr; +} + + +void +SetFragmentPtr(struct alias_link *link, char *fptr) +{ + link->data.frag_ptr = fptr; +} + + +void +GetFragmentPtr(struct alias_link *link, char **fptr) +{ + *fptr = link->data.frag_ptr; +} + + +void +SetStateIn(struct alias_link *link, int state) +{ + /* TCP input state */ + switch (state) { + case ALIAS_TCP_STATE_DISCONNECTED: + if (link->data.tcp->state.out != ALIAS_TCP_STATE_CONNECTED) { + link->expire_time = TCP_EXPIRE_DEAD; + } else { + link->expire_time = TCP_EXPIRE_SINGLEDEAD; + } + link->data.tcp->state.in = state; + break; + case ALIAS_TCP_STATE_CONNECTED: + link->expire_time = TCP_EXPIRE_CONNECTED; + /*FALLTHROUGH*/ + case ALIAS_TCP_STATE_NOT_CONNECTED: + link->data.tcp->state.in = state; + break; + default: + abort(); + } +} + + +void +SetStateOut(struct alias_link *link, int state) +{ + /* TCP output state */ + switch (state) { + case ALIAS_TCP_STATE_DISCONNECTED: + if (link->data.tcp->state.in != ALIAS_TCP_STATE_CONNECTED) { + link->expire_time = TCP_EXPIRE_DEAD; + } else { + link->expire_time = TCP_EXPIRE_SINGLEDEAD; + } + link->data.tcp->state.out = state; + break; + case ALIAS_TCP_STATE_CONNECTED: + link->expire_time = TCP_EXPIRE_CONNECTED; + /*FALLTHROUGH*/ + case ALIAS_TCP_STATE_NOT_CONNECTED: + link->data.tcp->state.out = state; + break; + default: + abort(); + } +} + + +int +GetStateIn(struct alias_link *link) +{ + /* TCP input state */ + return link->data.tcp->state.in; +} + + +int +GetStateOut(struct alias_link *link) +{ + /* TCP output state */ + return link->data.tcp->state.out; +} + + +struct in_addr +GetOriginalAddress(struct alias_link *link) +{ + if (link->src_addr.s_addr == 0) + return aliasAddress; + else + return(link->src_addr); +} + + +struct in_addr +GetDestAddress(struct alias_link *link) +{ + return(link->dst_addr); +} + + +struct in_addr +GetAliasAddress(struct alias_link *link) +{ + if (link->alias_addr.s_addr == 0) + return aliasAddress; + else + return link->alias_addr; +} + + +struct in_addr +GetDefaultAliasAddress() +{ + return aliasAddress; +} + + +void +SetDefaultAliasAddress(struct in_addr alias_addr) +{ + aliasAddress = alias_addr; +} + + +u_short +GetOriginalPort(struct alias_link *link) +{ + return(link->src_port); +} + + +u_short +GetAliasPort(struct alias_link *link) +{ + return(link->alias_port); +} + +u_short +GetDestPort(struct alias_link *link) +{ + return(link->dst_port); +} + +void +SetAckModified(struct alias_link *link) +{ +/* Indicate that ack numbers have been modified in a TCP connection */ + link->data.tcp->state.ack_modified = 1; +} + + +struct in_addr +GetProxyAddress(struct alias_link *link) +{ + return link->proxy_addr; +} + + +void +SetProxyAddress(struct alias_link *link, struct in_addr addr) +{ + link->proxy_addr = addr; +} + + +u_short +GetProxyPort(struct alias_link *link) +{ + return link->proxy_port; +} + + +void +SetProxyPort(struct alias_link *link, u_short port) +{ + link->proxy_port = port; +} + + +int +GetAckModified(struct alias_link *link) +{ +/* See if ack numbers have been modified */ + return link->data.tcp->state.ack_modified; +} + + +int +GetDeltaAckIn(struct ip *pip, struct alias_link *link) +{ +/* +Find out how much the ack number has been altered for an incoming +TCP packet. To do this, a circular list is ack numbers where the TCP +packet size was altered is searched. +*/ + + int i; + struct tcphdr *tc; + int delta, ack_diff_min; + u_long ack; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + ack = tc->th_ack; + + delta = 0; + ack_diff_min = -1; + for (i=0; idata.tcp->ack[i]; + if (x.active == 1) + { + int ack_diff; + + ack_diff = SeqDiff(x.ack_new, ack); + if (ack_diff >= 0) + { + if (ack_diff_min >= 0) + { + if (ack_diff < ack_diff_min) + { + delta = x.delta; + ack_diff_min = ack_diff; + } + } + else + { + delta = x.delta; + ack_diff_min = ack_diff; + } + } + } + } + return (delta); +} + + +int +GetDeltaSeqOut(struct ip *pip, struct alias_link *link) +{ +/* +Find out how much the seq number has been altered for an outgoing +TCP packet. To do this, a circular list is ack numbers where the TCP +packet size was altered is searched. +*/ + + int i; + struct tcphdr *tc; + int delta, seq_diff_min; + u_long seq; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + seq = tc->th_seq; + + delta = 0; + seq_diff_min = -1; + for (i=0; idata.tcp->ack[i]; + if (x.active == 1) + { + int seq_diff; + + seq_diff = SeqDiff(x.ack_old, seq); + if (seq_diff >= 0) + { + if (seq_diff_min >= 0) + { + if (seq_diff < seq_diff_min) + { + delta = x.delta; + seq_diff_min = seq_diff; + } + } + else + { + delta = x.delta; + seq_diff_min = seq_diff; + } + } + } + } + return (delta); +} + + +void +AddSeq(struct ip *pip, struct alias_link *link, int delta) +{ +/* +When a TCP packet has been altered in length, save this +information in a circular list. If enough packets have +been altered, then this list will begin to overwrite itself. +*/ + + struct tcphdr *tc; + struct ack_data_record x; + int hlen, tlen, dlen; + int i; + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + + hlen = (pip->ip_hl + tc->th_off) << 2; + tlen = ntohs(pip->ip_len); + dlen = tlen - hlen; + + x.ack_old = htonl(ntohl(tc->th_seq) + dlen); + x.ack_new = htonl(ntohl(tc->th_seq) + dlen + delta); + x.delta = delta; + x.active = 1; + + i = link->data.tcp->state.index; + link->data.tcp->ack[i] = x; + + i++; + if (i == N_LINK_TCP_DATA) + link->data.tcp->state.index = 0; + else + link->data.tcp->state.index = i; +} + +void +SetExpire(struct alias_link *link, int expire) +{ + if (expire == 0) + { + link->flags &= ~LINK_PERMANENT; + DeleteLink(link); + } + else if (expire == -1) + { + link->flags |= LINK_PERMANENT; + } + else if (expire > 0) + { + link->expire_time = expire; + } + else + { +#ifdef DEBUG + fprintf(stderr, "PacketAlias/SetExpire(): "); + fprintf(stderr, "error in expire parameter\n"); +#endif + } +} + +void +ClearCheckNewLink(void) +{ + newDefaultLink = 0; +} + + +/* Miscellaneous Functions + + HouseKeeping() + InitPacketAliasLog() + UninitPacketAliasLog() +*/ + +/* + Whenever an outgoing or incoming packet is handled, HouseKeeping() + is called to find and remove timed-out aliasing links. Logic exists + to sweep through the entire table and linked list structure + every 60 seconds. + + (prototype in alias_local.h) +*/ + +void +HouseKeeping(void) +{ + int i, n, n100; + struct timeval tv; + struct timezone tz; + + /* + * Save system time (seconds) in global variable timeStamp for + * use by other functions. This is done so as not to unnecessarily + * waste timeline by making system calls. + */ + gettimeofday(&tv, &tz); + timeStamp = tv.tv_sec; + + /* Compute number of spokes (output table link chains) to cover */ + n100 = LINK_TABLE_OUT_SIZE * 100 + houseKeepingResidual; + n100 *= timeStamp - lastCleanupTime; + n100 /= ALIAS_CLEANUP_INTERVAL_SECS; + + n = n100/100; + + /* Handle different cases */ + if (n > ALIAS_CLEANUP_MAX_SPOKES) + { + n = ALIAS_CLEANUP_MAX_SPOKES; + lastCleanupTime = timeStamp; + houseKeepingResidual = 0; + + for (i=0; i 0) + { + lastCleanupTime = timeStamp; + houseKeepingResidual = n100 - 100*n; + + for (i=0; iflags |= LINK_PERMANENT; + } +#ifdef DEBUG + else + { + fprintf(stderr, "PacketAliasRedirectPort(): " + "call to AddLink() failed\n"); + } +#endif + + return link; +} + +/* Translate PPTP packets to a machine on the inside + */ +int +PacketAliasPptp(struct in_addr src_addr) +{ + + pptpAliasAddr = src_addr; /* Address of the inside PPTP machine */ + pptpAliasFlag = src_addr.s_addr != INADDR_NONE; + + return 1; +} + +int GetPptpAlias (struct in_addr* alias_addr) +{ + if (pptpAliasFlag) + *alias_addr = pptpAliasAddr; + + return pptpAliasFlag; +} + +/* Static address translation */ +struct alias_link * +PacketAliasRedirectAddr(struct in_addr src_addr, + struct in_addr alias_addr) +{ + struct alias_link *link; + + link = AddLink(src_addr, nullAddress, alias_addr, + 0, 0, 0, + LINK_ADDR); + + if (link != NULL) + { + link->flags |= LINK_PERMANENT; + } +#ifdef DEBUG + else + { + fprintf(stderr, "PacketAliasRedirectAddr(): " + "call to AddLink() failed\n"); + } +#endif + + return link; +} + + +void +PacketAliasRedirectDelete(struct alias_link *link) +{ +/* This is a dangerous function to put in the API, + because an invalid pointer can crash the program. */ + + deleteAllLinks = 1; + DeleteLink(link); + deleteAllLinks = 0; +} + + +void +PacketAliasSetAddress(struct in_addr addr) +{ + if (packetAliasMode & PKT_ALIAS_RESET_ON_ADDR_CHANGE + && aliasAddress.s_addr != addr.s_addr) + CleanupAliasData(); + + aliasAddress = addr; +} + + +void +PacketAliasSetTarget(struct in_addr target_addr) +{ + targetAddress = target_addr; +} + + +void +PacketAliasInit(void) +{ + int i; + struct timeval tv; + struct timezone tz; + static int firstCall = 1; + + if (firstCall == 1) + { + gettimeofday(&tv, &tz); + timeStamp = tv.tv_sec; + lastCleanupTime = tv.tv_sec; + houseKeepingResidual = 0; + + for (i=0; i +#include +#include +#include +#include + +static void ClearAllFWHoles(void); + +static int fireWallBaseNum; /* The first firewall entry free for our use */ +static int fireWallNumNums; /* How many entries can we use? */ +static int fireWallActiveNum; /* Which entry did we last use? */ +static char *fireWallField; /* bool array for entries */ + +#define fw_setfield(field, num) \ +do { \ + (field)[num] = 1; \ +} /*lint -save -e717 */ while(0) /*lint -restore */ +#define fw_clrfield(field, num) \ +do { \ + (field)[num] = 0; \ +} /*lint -save -e717 */ while(0) /*lint -restore */ +#define fw_tstfield(field, num) ((field)[num]) + +void +PacketAliasSetFWBase(unsigned int base, unsigned int num) { + fireWallBaseNum = base; + fireWallNumNums = num; +} + +static void +InitPunchFW(void) { + fireWallField = malloc(fireWallNumNums); + if (fireWallField) { + memset(fireWallField, 0, fireWallNumNums); + if (fireWallFD < 0) { + fireWallFD = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); + } + ClearAllFWHoles(); + fireWallActiveNum = fireWallBaseNum; + } +} + +static void +UninitPunchFW(void) { + ClearAllFWHoles(); + if (fireWallFD >= 0) + close(fireWallFD); + fireWallFD = -1; + if (fireWallField) + free(fireWallField); + fireWallField = NULL; + packetAliasMode &= ~PKT_ALIAS_PUNCH_FW; +} + +/* Make a certain link go through the firewall */ +void +PunchFWHole(struct alias_link *link) { + int r; /* Result code */ + struct ip_fw rule; /* On-the-fly built rule */ + int fwhole; /* Where to punch hole */ + +/* Don't do anything unless we are asked to */ + if ( !(packetAliasMode & PKT_ALIAS_PUNCH_FW) || + fireWallFD < 0 || + link->link_type != LINK_TCP || + !link->data.tcp) + return; + + memset(&rule, 0, sizeof rule); + +/** Build rule **/ + + /* Find empty slot */ + for (fwhole = fireWallActiveNum; + fwhole < fireWallBaseNum + fireWallNumNums && + fw_tstfield(fireWallField, fwhole); + fwhole++) + ; + if (fwhole >= fireWallBaseNum + fireWallNumNums || + fw_tstfield(fireWallField, fwhole)) { + for (fwhole = fireWallBaseNum; + fwhole < fireWallActiveNum && + fw_tstfield(fireWallField, fwhole); + fwhole++) + ; + if (fwhole == fireWallActiveNum) { + /* No rule point empty - we can't punch more holes. */ + fireWallActiveNum = fireWallBaseNum; +#ifdef DEBUG + fprintf(stderr, "libalias: Unable to create firewall hole!\n"); +#endif + return; + } + } + /* Start next search at next position */ + fireWallActiveNum = fwhole+1; + + /* Build generic part of the two rules */ + rule.fw_number = fwhole; + rule.fw_nports = 1; /* Number of source ports; dest ports follow */ + rule.fw_flg = IP_FW_F_ACCEPT; + rule.fw_prot = IPPROTO_TCP; + rule.fw_smsk.s_addr = INADDR_BROADCAST; + rule.fw_dmsk.s_addr = INADDR_BROADCAST; + + /* Build and apply specific part of the rules */ + rule.fw_src = GetOriginalAddress(link); + rule.fw_dst = GetDestAddress(link); + rule.fw_uar.fw_pts[0] = ntohs(GetOriginalPort(link)); + rule.fw_uar.fw_pts[1] = ntohs(GetDestPort(link)); + + /* Skip non-bound links - XXX should not be strictly necessary, + but seems to leave hole if not done. Leak of non-bound links? + (Code should be left even if the problem is fixed - it is a + clear optimization) */ + if (rule.fw_uar.fw_pts[0] != 0 && rule.fw_uar.fw_pts[1] != 0) { + r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); +#ifdef DEBUG + if (r) + err(1, "alias punch inbound(1) setsockopt(IP_FW_ADD)"); +#endif + rule.fw_src = GetDestAddress(link); + rule.fw_dst = GetOriginalAddress(link); + rule.fw_uar.fw_pts[0] = ntohs(GetDestPort(link)); + rule.fw_uar.fw_pts[1] = ntohs(GetOriginalPort(link)); + r = setsockopt(fireWallFD, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); +#ifdef DEBUG + if (r) + err(1, "alias punch inbound(2) setsockopt(IP_FW_ADD)"); +#endif + } +/* Indicate hole applied */ + link->data.tcp->fwhole = fwhole; + fw_setfield(fireWallField, fwhole); +} + +/* Remove a hole in a firewall associated with a particular alias + link. Calling this too often is harmless. */ +static void +ClearFWHole(struct alias_link *link) { + if (link->link_type == LINK_TCP && link->data.tcp) { + int fwhole = link->data.tcp->fwhole; /* Where is the firewall hole? */ + struct ip_fw rule; + + if (fwhole < 0) + return; + + memset(&rule, 0, sizeof rule); + rule.fw_number = fwhole; + while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule)) + ; + fw_clrfield(fireWallField, fwhole); + link->data.tcp->fwhole = -1; + } +} + +/* Clear out the entire range dedicated to firewall holes. */ +static void +ClearAllFWHoles(void) { + struct ip_fw rule; /* On-the-fly built rule */ + int i; + + if (fireWallFD < 0) + return; + + memset(&rule, 0, sizeof rule); + for (i = fireWallBaseNum; i < fireWallBaseNum + fireWallNumNums; i++) { + rule.fw_number = i; + while (!setsockopt(fireWallFD, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule)) + ; + } + memset(fireWallField, 0, fireWallNumNums); +} +#endif diff --git a/alias/alias_ftp.c b/alias/alias_ftp.c new file mode 100644 index 0000000..73769fd --- /dev/null +++ b/alias/alias_ftp.c @@ -0,0 +1,229 @@ +/* + Alias_ftp.c performs special processing for FTP sessions under + TCP. Specifically, when a PORT command from the client side + is sent, it is intercepted and modified. The address is changed + to the gateway machine and an aliasing port is used. + + For this routine to work, the PORT command must fit entirely + into a single TCP packet. This is typically the case, but exceptions + can easily be envisioned under the actual specifications. + + Probably the most troubling aspect of the approach taken here is + that the new PORT command will typically be a different length, and + this causes a certain amount of bookkeeping to keep track of the + changes of sequence and acknowledgment numbers, since the client + machine is totally unaware of the modification to the TCP stream. + + + This software is placed into the public domain with no restrictions + on its distribution. + + Initial version: August, 1996 (cjm) + + Version 1.6 + Brian Somers and Martin Renters identified an IP checksum + error for modified IP packets. + + Version 1.7: January 9, 1996 (cjm) + Differental checksum computation for change + in IP packet length. + + Version 2.1: May, 1997 (cjm) + Very minor changes to conform with + local/global/function naming conventions + withing the packet alising module. + + See HISTORY file for record of revisions. +*/ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alias_local.h" + +static void NewFtpPortCommand(struct ip *, struct alias_link *, struct in_addr, u_short, int); + + + +void +AliasHandleFtpOut( +struct ip *pip, /* IP packet to examine/patch */ +struct alias_link *link, /* The link to go through (aliased port) */ +int maxpacketsize /* The maximum size this packet can grow to (including headers) */) +{ + int hlen, tlen, dlen; + struct in_addr true_addr; + u_short true_port; + char *sptr; + struct tcphdr *tc; + +/* Calculate data length of TCP packet */ + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + hlen = (pip->ip_hl + tc->th_off) << 2; + tlen = ntohs(pip->ip_len); + dlen = tlen - hlen; + +/* Return is data length is too long or too short */ + if (dlen<10 || dlen>80) + return; + +/* Place string pointer and beginning of data */ + sptr = (char *) pip; + sptr += hlen; + +/* Parse through string using state diagram method */ + { + char ch, zero; + int i, state; + u_long a1, a2, a3, a4; + u_short p1, p2; + + a1=0; a2=0; a3=0; a4=0; p1=0; p2=0; + zero = '0'; + state=-4; + for (i=0; iip_hl << 2)); + hlen = (pip->ip_hl + tc->th_off) << 2; + tlen = ntohs(pip->ip_len); + dlen = tlen - hlen; + +/* Create new PORT command */ + { + char stemp[80]; + char *sptr; + u_short alias_port; + u_char *ptr; + int a1, a2, a3, a4, p1, p2; + struct in_addr alias_address; + +/* Decompose alias address into quad format */ + alias_address = GetAliasAddress(link); + ptr = (u_char *) &alias_address.s_addr; + a1 = *ptr++; a2=*ptr++; a3=*ptr++; a4=*ptr; + +/* Decompose alias port into pair format */ + alias_port = GetAliasPort(ftp_link); + ptr = (char *) &alias_port; + p1 = *ptr++; p2=*ptr; + +/* Generate command string */ + sprintf(stemp, "PORT %d,%d,%d,%d,%d,%d\r\n", + a1,a2,a3,a4,p1,p2); + +/* Save string length for IP header modification */ + slen = strlen(stemp); + +/* Copy into IP packet */ + sptr = (char *) pip; sptr += hlen; + strncpy(sptr, stemp, maxpacketsize-hlen); + } + +/* Save information regarding modified seq and ack numbers */ + { + int delta; + + SetAckModified(link); + delta = GetDeltaSeqOut(pip, link); + AddSeq(pip, link, delta+slen-dlen); + } + +/* Revise IP header */ + { + u_short new_len; + + new_len = htons(hlen + slen); + DifferentialChecksum(&pip->ip_sum, + &new_len, + &pip->ip_len, + 1); + pip->ip_len = new_len; + } + +/* Compute TCP checksum for revised packet */ + tc->th_sum = 0; + tc->th_sum = TcpChecksum(pip); + } + else + { +#ifdef DEBUG + fprintf(stderr, + "PacketAlias/HandleFtpOut: Cannot allocate FTP data port\n"); +#endif + } +} diff --git a/alias/alias_irc.c b/alias/alias_irc.c new file mode 100644 index 0000000..910e934 --- /dev/null +++ b/alias/alias_irc.c @@ -0,0 +1,316 @@ +/* Alias_irc.c intercepts packages contain IRC CTCP commands, and + changes DCC commands to export a port on the aliasing host instead + of an aliased host. + + For this routine to work, the DCC command must fit entirely into a + single TCP packet. This will usually happen, but is not + guaranteed. + + The interception is likely to change the length of the packet. + The handling of this is copied more-or-less verbatim from + ftp_alias.c + + This software is placed into the public domain with no restrictions + on its distribution. + + Initial version: Eivind Eklund (ee) 97-01-29 + + Version 2.1: May, 1997 (cjm) + Very minor changes to conform with + local/global/function naming conventions + withing the packet alising module. +*/ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alias_local.h" + +/* Local defines */ +#define DBprintf(a) + + +void +AliasHandleIrcOut(struct ip *pip, /* IP packet to examine */ + struct alias_link *link, /* Which link are we on? */ + int maxsize /* Maximum size of IP packet including headers */ + ) +{ + int hlen, tlen, dlen; + struct in_addr true_addr; + u_short true_port; + char *sptr; + struct tcphdr *tc; + int i; /* Iterator through the source */ + +/* Calculate data length of TCP packet */ + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + hlen = (pip->ip_hl + tc->th_off) << 2; + tlen = ntohs(pip->ip_len); + dlen = tlen - hlen; + + /* Return if data length is too short - assume an entire PRIVMSG in each packet. */ + if (dlen= dlen || iCopy >= sizeof(newpacket) ) + goto lPACKET_DONE; + newpacket[iCopy++] = sptr[i++]; /* Copy the CTCP start character */ + /* Start of a CTCP */ + if( i+4 >= dlen ) /* Too short for DCC */ + goto lBAD_CTCP; + if( sptr[i+0] != 'D' ) + goto lBAD_CTCP; + if( sptr[i+1] != 'C' ) + goto lBAD_CTCP; + if( sptr[i+2] != 'C' ) + goto lBAD_CTCP; + if( sptr[i+3] != ' ' ) + goto lBAD_CTCP; + /* We have a DCC command - handle it! */ + i+= 4; /* Skip "DCC " */ + if( iCopy+4 > sizeof(newpacket) ) + goto lPACKET_DONE; + newpacket[iCopy++] = 'D'; + newpacket[iCopy++] = 'C'; + newpacket[iCopy++] = 'C'; + newpacket[iCopy++] = ' '; + + DBprintf(("Found DCC\n")); + /* Skip any extra spaces (should not occur according to + protocol, but DCC breaks CTCP protocol anyway */ + while(sptr[i] == ' ') { + if( ++i >= dlen) { + DBprintf(("DCC packet terminated in just spaces\n")); + goto lPACKET_DONE; + } + } + + DBprintf(("Transferring command...\n")); + while(sptr[i] != ' ') { + newpacket[iCopy++] = sptr[i]; + if( ++i >= dlen || iCopy >= sizeof(newpacket) ) { + DBprintf(("DCC packet terminated during command\n")); + goto lPACKET_DONE; + } + } + /* Copy _one_ space */ + if( i+1 < dlen && iCopy < sizeof(newpacket) ) + newpacket[iCopy++] = sptr[i++]; + + DBprintf(("Done command - removing spaces\n")); + /* Skip any extra spaces (should not occur according to + protocol, but DCC breaks CTCP protocol anyway */ + while(sptr[i] == ' ') { + if( ++i >= dlen ) { + DBprintf(("DCC packet terminated in just spaces (post-command)\n")); + goto lPACKET_DONE; + } + } + + DBprintf(("Transferring filename...\n")); + while(sptr[i] != ' ') { + newpacket[iCopy++] = sptr[i]; + if( ++i >= dlen || iCopy >= sizeof(newpacket) ) { + DBprintf(("DCC packet terminated during filename\n")); + goto lPACKET_DONE; + } + } + /* Copy _one_ space */ + if( i+1 < dlen && iCopy < sizeof(newpacket) ) + newpacket[iCopy++] = sptr[i++]; + + DBprintf(("Done filename - removing spaces\n")); + /* Skip any extra spaces (should not occur according to + protocol, but DCC breaks CTCP protocol anyway */ + while(sptr[i] == ' ') { + if( ++i >= dlen ) { + DBprintf(("DCC packet terminated in just spaces (post-filename)\n")); + goto lPACKET_DONE; + } + } + + DBprintf(("Fetching IP address\n")); + /* Fetch IP address */ + org_addr = 0; + while(i ULONG_MAX/10UL ) { /* Terminate on overflow */ + DBprintf(("DCC Address overflow (org_addr == 0x%08lx, next char %c\n", org_addr, sptr[i])); + goto lBAD_CTCP; + } + org_addr *= 10; + org_addr += sptr[i++]-'0'; + } + DBprintf(("Skipping space\n")); + if( i+1 >= dlen || sptr[i] != ' ' ) { + DBprintf(("Overflow (%d >= %d) or bad character (%02x) terminating IP address\n", i+1, dlen, sptr[i])); + goto lBAD_CTCP; + } + /* Skip any extra spaces (should not occur according to + protocol, but DCC breaks CTCP protocol anyway, so we might + as well play it safe */ + while(sptr[i] == ' ') { + if( ++i >= dlen ) { + DBprintf(("Packet failure - space overflow.\n")); + goto lPACKET_DONE; + } + } + DBprintf(("Fetching port number\n")); + /* Fetch source port */ + org_port = 0; + while(i 6554 ) { /* Terminate on overflow (65536/10 rounded up*/ + DBprintf(("DCC: port number overflow\n")); + goto lBAD_CTCP; + } + org_port *= 10; + org_port += sptr[i++]-'0'; + } + /* Skip illegal addresses (or early termination) */ + if( i >= dlen || (sptr[i] != '\001' && sptr[i] != ' ') ) { + DBprintf(("Bad port termination\n")); + goto lBAD_CTCP; + } + DBprintf(("Got IP %lu and port %u\n", org_addr, (unsigned)org_port)); + + /* We've got the address and port - now alias it */ + { + struct alias_link *dcc_link; + struct in_addr destaddr; + + + true_port = htons(org_port); + true_addr.s_addr = htonl(org_addr); + destaddr.s_addr = 0; + + /* Steal the FTP_DATA_PORT - it doesn't really matter, and this + would probably allow it through at least _some_ + firewalls. */ + dcc_link = FindUdpTcpOut (true_addr, + destaddr, + true_port, + 0, IPPROTO_TCP); + DBprintf(("Got a DCC link\n")); + if ( dcc_link ) { + struct in_addr alias_address; /* Address from aliasing */ + u_short alias_port; /* Port given by aliasing */ + +#ifndef NO_FW_PUNCH + /* Generate firewall hole as appropriate */ + PunchFWHole(dcc_link); +#endif + + alias_address = GetAliasAddress(link); + iCopy += snprintf(&newpacket[iCopy], + sizeof(newpacket)-iCopy, + "%lu ", (u_long)htonl(alias_address.s_addr)); + if( iCopy >= sizeof(newpacket) ) { /* Truncated/fit exactly - bad news */ + DBprintf(("DCC constructed packet overflow.\n")); + goto lBAD_CTCP; + } + alias_port = GetAliasPort(dcc_link); + iCopy += snprintf(&newpacket[iCopy], + sizeof(newpacket)-iCopy, + "%u", htons(alias_port) ); + /* Done - truncated cases will be taken care of by lBAD_CTCP */ + DBprintf(("Aliased IP %lu and port %u\n", alias_address.s_addr, (unsigned)alias_port)); + } + } + /* An uninteresting CTCP - state entered right after '\001' has + been pushed. Also used to copy the rest of a DCC, after IP + address and port has been handled */ + lBAD_CTCP: + for(; i maxsize-copyat ? maxsize-copyat : iCopy; + memcpy(sptr+copyat, newpacket, iCopy); + +/* Save information regarding modified seq and ack numbers */ + { + int delta; + + SetAckModified(link); + delta = GetDeltaSeqOut(pip, link); + AddSeq(pip, link, delta+copyat+iCopy-dlen); + } + + /* Revise IP header */ + { + u_short new_len; + + new_len = htons(hlen + iCopy + copyat); + DifferentialChecksum(&pip->ip_sum, + &new_len, + &pip->ip_len, + 1); + pip->ip_len = new_len; + } + + /* Compute TCP checksum for revised packet */ + tc->th_sum = 0; + tc->th_sum = TcpChecksum(pip); + return; + } +} + +/* Notes: + [Note 1] + The initial search will most often fail; it could be replaced with a 32-bit specific search. + Such a search would be done for 32-bit unsigned value V: + V ^= 0x01010101; (Search is for null bytes) + if( ((V-0x01010101)^V) & 0x80808080 ) { + (found a null bytes which was a 01 byte) + } + To assert that the processor is 32-bits, do + extern int ircdccar[32]; (32 bits) + extern int ircdccar[CHAR_BIT*sizeof(unsigned int)]; + which will generate a type-error on all but 32-bit machines. + + [Note 2] This routine really ought to be replaced with one that + creates a transparent proxy on the aliasing host, to allow arbitary + changes in the TCP stream. This should not be too difficult given + this base; I (ee) will try to do this some time later. + */ diff --git a/alias/alias_local.h b/alias/alias_local.h new file mode 100644 index 0000000..23b04a8 --- /dev/null +++ b/alias/alias_local.h @@ -0,0 +1,170 @@ +/* -*- mode: c; tab-width: 3; c-basic-offset: 3; -*- + Alias_local.h contains the function prototypes for alias.c, + alias_db.c, alias_util.c and alias_ftp.c, alias_irc.c (as well + as any future add-ons). It also includes macros, globals and + struct definitions shared by more than one alias*.c file. + + This include file is intended to be used only within the aliasing + software. Outside world interfaces are defined in alias.h + + This software is placed into the public domain with no restrictions + on its distribution. + + Initial version: August, 1996 (cjm) + + +*/ +#ifndef ALIAS_LOCAL_H +#define ALIAS_LOCAL_H + + +/* + Macros + */ + +/* + The following macro is used to update an + internet checksum. "delta" is a 32-bit + accumulation of all the changes to the + checksum (adding in new 16-bit words and + subtracting out old words), and "cksum" + is the checksum value to be updated. +*/ +#define ADJUST_CHECKSUM(acc, cksum) { \ + acc += cksum; \ + if (acc < 0) \ + { \ + acc = -acc; \ + acc = (acc >> 16) + (acc & 0xffff); \ + acc += acc >> 16; \ + cksum = (u_short) ~acc; \ + } \ + else \ + { \ + acc = (acc >> 16) + (acc & 0xffff); \ + acc += acc >> 16; \ + cksum = (u_short) acc; \ + } \ +} + + +/* + Globals +*/ + +extern int packetAliasMode; + + +/* + Structs +*/ + +struct alias_link; /* Incomplete structure */ + + +/* + Prototypes +*/ + +/* General utilities */ +u_short IpChecksum(struct ip *); +u_short TcpChecksum(struct ip *); +void DifferentialChecksum(u_short *, u_short *, u_short *, int); + +/* Internal data access */ +struct alias_link * +FindIcmpIn(struct in_addr, struct in_addr, u_short); + +struct alias_link * +FindIcmpOut(struct in_addr, struct in_addr, u_short); + +struct alias_link * +FindFragmentIn1(struct in_addr, struct in_addr, u_short); + +struct alias_link * +FindFragmentIn2(struct in_addr, struct in_addr, u_short); + +struct alias_link * +AddFragmentPtrLink(struct in_addr, u_short); + +struct alias_link * +FindFragmentPtr(struct in_addr, u_short); + +struct alias_link * +FindUdpTcpIn (struct in_addr, struct in_addr, u_short, u_short, u_char); + +struct alias_link * +FindUdpTcpOut(struct in_addr, struct in_addr, u_short, u_short, u_char); + +struct in_addr +FindOriginalAddress(struct in_addr); + +struct in_addr +FindAliasAddress(struct in_addr); + +/* External data access/modification */ +void GetFragmentAddr(struct alias_link *, struct in_addr *); +void SetFragmentAddr(struct alias_link *, struct in_addr); +void GetFragmentPtr(struct alias_link *, char **); +void SetFragmentPtr(struct alias_link *, char *); +void SetStateIn(struct alias_link *, int); +void SetStateOut(struct alias_link *, int); +int GetStateIn(struct alias_link *); +int GetStateOut(struct alias_link *); +struct in_addr GetOriginalAddress(struct alias_link *); +struct in_addr GetDestAddress(struct alias_link *); +struct in_addr GetAliasAddress(struct alias_link *); +struct in_addr GetDefaultAliasAddress(void); +void SetDefaultAliasAddress(struct in_addr); +u_short GetOriginalPort(struct alias_link *); +u_short GetAliasPort(struct alias_link *); +struct in_addr GetProxyAddress(struct alias_link *); +void SetProxyAddress(struct alias_link *, struct in_addr); +u_short GetProxyPort(struct alias_link *); +void SetProxyPort(struct alias_link *, u_short); +void SetAckModified(struct alias_link *); +int GetAckModified(struct alias_link *); +int GetDeltaAckIn(struct ip *, struct alias_link *); +int GetDeltaSeqOut(struct ip *, struct alias_link *); +void AddSeq(struct ip *, struct alias_link *, int); +void SetExpire(struct alias_link *, int); +void ClearCheckNewLink(void); +#ifndef NO_FW_PUNCH +void PunchFWHole(struct alias_link *); +#endif + + +/* Housekeeping function */ +void HouseKeeping(void); + +/* Tcp specfic routines */ +/*lint -save -library Suppress flexelint warnings */ + +/* FTP routines */ +void AliasHandleFtpOut(struct ip *, struct alias_link *, int); + +/* IRC routines */ +void AliasHandleIrcOut(struct ip *, struct alias_link *, int); + +/* NetBIOS routines */ +int AliasHandleUdpNbt(struct ip *, struct alias_link *, struct in_addr *, u_short); +int AliasHandleUdpNbtNS(struct ip *, struct alias_link *, struct in_addr *, u_short *, struct in_addr *, u_short *); + +/* CUSeeMe routines */ +void AliasHandleCUSeeMeOut(struct ip *, struct alias_link *); +void AliasHandleCUSeeMeIn(struct ip *, struct in_addr); + +/* Transparent proxy routines */ +int ProxyCheck(struct ip *, struct in_addr *, u_short *); +void ProxyModify(struct alias_link *, struct ip *, int, int); + + +enum alias_tcp_state { + ALIAS_TCP_STATE_NOT_CONNECTED, + ALIAS_TCP_STATE_CONNECTED, + ALIAS_TCP_STATE_DISCONNECTED +}; + +int GetPptpAlias (struct in_addr*); +/*lint -restore */ +#endif /* defined(ALIAS_LOCAL_H) */ diff --git a/alias/alias_nbt.c b/alias/alias_nbt.c new file mode 100644 index 0000000..b629b8e --- /dev/null +++ b/alias/alias_nbt.c @@ -0,0 +1,711 @@ +/* + * Written by Atsushi Murai + * + * Copyright (C) 1998, System Planning and Engineering Co. All rights reserverd. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the System Planning and Engineering Co. The name of the + * SPEC may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * $Id: alias_nbt.c,v 1.1.1.1 2000/01/11 01:48:42 wsanchez Exp $ + * + * TODO: + * oClean up. + * oConsidering for word alignment for other platform. + */ +/* + alias_nbt.c performs special processing for NetBios over TCP/IP + sessions by UDP. + + Initial version: May, 1998 (Atsushi Murai ) + + See HISTORY file for record of revisions. +*/ + +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alias_local.h" + +#define ADJUST_CHECKSUM(acc, cksum) { \ + acc += cksum; \ + if (acc < 0) \ + { \ + acc = -acc; \ + acc = (acc >> 16) + (acc & 0xffff); \ + acc += acc >> 16; \ + cksum = (u_short) ~acc; \ + } \ + else \ + { \ + acc = (acc >> 16) + (acc & 0xffff); \ + acc += acc >> 16; \ + cksum = (u_short) acc; \ + } \ +} + +typedef struct { + struct in_addr oldaddr; + u_short oldport; + struct in_addr newaddr; + u_short newport; + u_short *uh_sum; +} NBTArguments; + +typedef struct { + unsigned char type; + unsigned char flags; + u_short id; + struct in_addr source_ip; + u_short source_port; + u_short len; + u_short offset; +} NbtDataHeader; + +#define OpQuery 0 +#define OpUnknown 4 +#define OpRegist 5 +#define OpRelease 6 +#define OpWACK 7 +#define OpRefresh 8 +typedef struct { + u_short nametrid; + u_short dir:1, opcode:4, nmflags:7, rcode:4; + u_short qdcount; + u_short ancount; + u_short nscount; + u_short arcount; +} NbtNSHeader; + +#define FMT_ERR 0x1 +#define SRV_ERR 0x2 +#define IMP_ERR 0x4 +#define RFS_ERR 0x5 +#define ACT_ERR 0x6 +#define CFT_ERR 0x7 + + +#ifdef DEBUG +static void PrintRcode( u_char rcode ) { + + switch (rcode) { + case FMT_ERR: + printf("\nFormat Error."); + case SRV_ERR: + printf("\nSever failure."); + case IMP_ERR: + printf("\nUnsupported request error.\n"); + case RFS_ERR: + printf("\nRefused error.\n"); + case ACT_ERR: + printf("\nActive error.\n"); + case CFT_ERR: + printf("\nName in conflict error.\n"); + default: + printf("\n???=%0x\n", rcode ); + + } +} +#endif + + +/* Handling Name field */ +static u_char *AliasHandleName ( u_char *p, char *pmax ) { + + u_char *s; + u_char c; + int compress; + + /* Following length field */ + + if (p == NULL || (char *)p >= pmax) + return(NULL); + + if (*p & 0xc0 ) { + p = p + 2; + if ((char *)p > pmax) + return(NULL); + return ((u_char *)p); + } + while ( ( *p & 0x3f) != 0x00 ) { + s = p + 1; + if ( *p == 0x20 ) + compress = 1; + else + compress = 0; + + /* Get next length field */ + p = (u_char *)(p + (*p & 0x3f) + 1); + if ((char *)p > pmax) { + p = NULL; + break; + } +#ifdef DEBUG + printf(":"); +#endif + while (s < p) { + if ( compress == 1 ) { + c = (u_char )(((((*s & 0x0f) << 4) | (*(s+1) & 0x0f)) - 0x11)); +#ifdef DEBUG + if (isprint( c ) ) + printf("%c", c ); + else + printf("<0x%02x>", c ); +#endif + s +=2; + } else { +#ifdef DEBUG + printf("%c", *s); +#endif + s++; + } + } +#ifdef DEBUG + printf(":"); +#endif + fflush(stdout); + } + + /* Set up to out of Name field */ + if (p == NULL || (char *)p >= pmax) + p = NULL; + else + p++; + return ((u_char *)p); +} + +/* + * NetBios Datagram Handler (IP/UDP) + */ +#define DGM_DIRECT_UNIQ 0x10 +#define DGM_DIRECT_GROUP 0x11 +#define DGM_BROADCAST 0x12 +#define DGM_ERROR 0x13 +#define DGM_QUERY 0x14 +#define DGM_POSITIVE_RES 0x15 +#define DGM_NEGATIVE_RES 0x16 + +int AliasHandleUdpNbt( + struct ip *pip, /* IP packet to examine/patch */ + struct alias_link *link, + struct in_addr *alias_address, + u_short alias_port +) { + struct udphdr * uh; + NbtDataHeader *ndh; + u_char *p = NULL; + char *pmax; + + /* Calculate data length of UDP packet */ + uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); + pmax = (char *)uh + ntohs( uh->uh_ulen ); + + ndh = (NbtDataHeader *)((char *)uh + (sizeof (struct udphdr))); + if ((char *)(ndh + 1) > pmax) + return(-1); +#ifdef DEBUG + printf("\nType=%02x,", ndh->type ); +#endif + switch ( ndh->type ) { + case DGM_DIRECT_UNIQ: + case DGM_DIRECT_GROUP: + case DGM_BROADCAST: + p = (u_char *)ndh + 14; + p = AliasHandleName ( p, pmax ); /* Source Name */ + p = AliasHandleName ( p, pmax ); /* Destination Name */ + break; + case DGM_ERROR: + p = (u_char *)ndh + 11; + break; + case DGM_QUERY: + case DGM_POSITIVE_RES: + case DGM_NEGATIVE_RES: + p = (u_char *)ndh + 10; + p = AliasHandleName ( p, pmax ); /* Destination Name */ + break; + } + if (p == NULL || (char *)p > pmax) + p = NULL; +#ifdef DEBUG + printf("%s:%d-->", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) ); +#endif + /* Doing a IP address and Port number Translation */ + if ( uh->uh_sum != 0 ) { + int acc; + u_short *sptr; + acc = ndh->source_port; + acc -= alias_port; + sptr = (u_short *) &(ndh->source_ip); + acc += *sptr++; + acc += *sptr; + sptr = (u_short *) alias_address; + acc -= *sptr++; + acc -= *sptr; + ADJUST_CHECKSUM(acc, uh->uh_sum) + } + ndh->source_ip = *alias_address; + ndh->source_port = alias_port; +#ifdef DEBUG + printf("%s:%d\n", inet_ntoa(ndh->source_ip), ntohs(ndh->source_port) ); + fflush(stdout); +#endif + return((p == NULL) ? -1 : 0); +} +/* Question Section */ +#define QS_TYPE_NB 0x0020 +#define QS_TYPE_NBSTAT 0x0021 +#define QS_CLAS_IN 0x0001 +typedef struct { + u_short type; /* The type of Request */ + u_short class; /* The class of Request */ +} NBTNsQuestion; + +static u_char * +AliasHandleQuestion( + u_short count, + NBTNsQuestion *q, + char *pmax, + NBTArguments *nbtarg) +{ + + while ( count != 0 ) { + /* Name Filed */ + q = (NBTNsQuestion *)AliasHandleName((u_char *)q, pmax); + + if (q == NULL || (char *)(q + 1) > pmax) { + q = NULL; + break; + } + + /* Type and Class filed */ + switch ( ntohs(q->type) ) { + case QS_TYPE_NB: + case QS_TYPE_NBSTAT: + q= q+1; + break; + default: +#ifdef DEBUG + printf("\nUnknown Type on Question %0x\n", ntohs(q->type) ); +#endif + break; + } + count--; + } + + /* Set up to out of Question Section */ + return ((u_char *)q); +} + +/* Resource Record */ +#define RR_TYPE_A 0x0001 +#define RR_TYPE_NS 0x0002 +#define RR_TYPE_NULL 0x000a +#define RR_TYPE_NB 0x0020 +#define RR_TYPE_NBSTAT 0x0021 +#define RR_CLAS_IN 0x0001 +#define SizeOfNsResource 8 +typedef struct { + u_short type; + u_short class; + unsigned int ttl; + u_short rdlen; +} NBTNsResource; + +#define SizeOfNsRNB 6 +typedef struct { + u_short g:1, ont:2, resv:13; + struct in_addr addr; +} NBTNsRNB; + +static u_char * +AliasHandleResourceNB( + NBTNsResource *q, + char *pmax, + NBTArguments *nbtarg) +{ + NBTNsRNB *nb; + u_short bcount; + + if (q == NULL || (char *)(q + 1) > pmax) + return(NULL); + /* Check out a length */ + bcount = ntohs(q->rdlen); + + /* Forward to Resource NB position */ + nb = (NBTNsRNB *)((u_char *)q + SizeOfNsResource); + + /* Processing all in_addr array */ +#ifdef DEBUG + printf("NB rec[%s", inet_ntoa(nbtarg->oldaddr)); + printf("->%s, %dbytes] ",inet_ntoa(nbtarg->newaddr ), bcount); +#endif + while ( nb != NULL && bcount != 0 ) { + if ((char *)(nb + 1) > pmax) { + nb = NULL; + break; + } +#ifdef DEBUG + printf("<%s>", inet_ntoa(nb->addr) ); +#endif + if (!bcmp(&nbtarg->oldaddr,&nb->addr, sizeof(struct in_addr) ) ) { + if ( *nbtarg->uh_sum != 0 ) { + int acc; + u_short *sptr; + + sptr = (u_short *) &(nb->addr); + acc = *sptr++; + acc += *sptr; + sptr = (u_short *) &(nbtarg->newaddr); + acc -= *sptr++; + acc -= *sptr; + ADJUST_CHECKSUM(acc, *nbtarg->uh_sum) + } + + nb->addr = nbtarg->newaddr; +#ifdef DEBUG + printf("O"); +#endif + } +#ifdef DEBUG + else { + printf("."); + } +#endif + nb=(NBTNsRNB *)((u_char *)nb + SizeOfNsRNB); + bcount -= SizeOfNsRNB; + } + if (nb == NULL || (char *)(nb + 1) > pmax) { + nb = NULL; + } + + return ((u_char *)nb); +} + +#define SizeOfResourceA 6 +typedef struct { + struct in_addr addr; +} NBTNsResourceA; + +static u_char * +AliasHandleResourceA( + NBTNsResource *q, + char *pmax, + NBTArguments *nbtarg) +{ + NBTNsResourceA *a; + u_short bcount; + + if (q == NULL || (char *)(q + 1) > pmax) + return(NULL); + + /* Forward to Resource A position */ + a = (NBTNsResourceA *)( (u_char *)q + sizeof(NBTNsResource) ); + + /* Check out of length */ + bcount = ntohs(q->rdlen); + + /* Processing all in_addr array */ +#ifdef DEBUG + printf("Arec [%s", inet_ntoa(nbtarg->oldaddr)); + printf("->%s]",inet_ntoa(nbtarg->newaddr )); +#endif + while ( bcount != 0 ) { + if (a == NULL || (char *)(a + 1) > pmax) + return(NULL); +#ifdef DEBUG + printf("..%s", inet_ntoa(a->addr) ); +#endif + if ( !bcmp(&nbtarg->oldaddr, &a->addr, sizeof(struct in_addr) ) ) { + if ( *nbtarg->uh_sum != 0 ) { + int acc; + u_short *sptr; + + sptr = (u_short *) &(a->addr); /* Old */ + acc = *sptr++; + acc += *sptr; + sptr = (u_short *) &nbtarg->newaddr; /* New */ + acc -= *sptr++; + acc -= *sptr; + ADJUST_CHECKSUM(acc, *nbtarg->uh_sum) + } + + a->addr = nbtarg->newaddr; + } + a++; /*XXXX*/ + bcount -= SizeOfResourceA; + } + if (a == NULL || (char *)(a + 1) > pmax) + a = NULL; + return ((u_char *)a); +} + +typedef struct { + u_short opcode:4, flags:8, resv:4; +} NBTNsResourceNULL; + +static u_char * +AliasHandleResourceNULL( + NBTNsResource *q, + char *pmax, + NBTArguments *nbtarg) +{ + NBTNsResourceNULL *n; + u_short bcount; + + if (q == NULL || (char *)(q + 1) > pmax) + return(NULL); + + /* Forward to Resource NULL position */ + n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) ); + + /* Check out of length */ + bcount = ntohs(q->rdlen); + + /* Processing all in_addr array */ + while ( bcount != 0 ) { + if ((char *)(n + 1) > pmax) { + n = NULL; + break; + } + n++; + bcount -= sizeof(NBTNsResourceNULL); + } + if ((char *)(n + 1) > pmax) + n = NULL; + + return ((u_char *)n); +} + +static u_char * +AliasHandleResourceNS( + NBTNsResource *q, + char *pmax, + NBTArguments *nbtarg) +{ + NBTNsResourceNULL *n; + u_short bcount; + + if (q == NULL || (char *)(q + 1) > pmax) + return(NULL); + + /* Forward to Resource NULL position */ + n = (NBTNsResourceNULL *)( (u_char *)q + sizeof(NBTNsResource) ); + + /* Check out of length */ + bcount = ntohs(q->rdlen); + + /* Resource Record Name Filed */ + q = (NBTNsResource *)AliasHandleName( (u_char *)n, pmax ); /* XXX */ + + if (q == NULL || (char *)((u_char *)n + bcount) > pmax) + return(NULL); + else + return ((u_char *)n + bcount); +} + +typedef struct { + u_short numnames; +} NBTNsResourceNBSTAT; + +static u_char * +AliasHandleResourceNBSTAT( + NBTNsResource *q, + char *pmax, + NBTArguments *nbtarg) +{ + NBTNsResourceNBSTAT *n; + u_short bcount; + + if (q == NULL || (char *)(q + 1) > pmax) + return(NULL); + + /* Forward to Resource NBSTAT position */ + n = (NBTNsResourceNBSTAT *)( (u_char *)q + sizeof(NBTNsResource) ); + + /* Check out of length */ + bcount = ntohs(q->rdlen); + + if (q == NULL || (char *)((u_char *)n + bcount) > pmax) + return(NULL); + else + return ((u_char *)n + bcount); +} + +static u_char * +AliasHandleResource( + u_short count, + NBTNsResource *q, + char *pmax, + NBTArguments + *nbtarg) +{ + while ( count != 0 ) { + /* Resource Record Name Filed */ + q = (NBTNsResource *)AliasHandleName( (u_char *)q, pmax ); + + if (q == NULL || (char *)(q + 1) > pmax) + break; +#ifdef DEBUG + printf("type=%02x, count=%d\n", ntohs(q->type), count ); +#endif + + /* Type and Class filed */ + switch ( ntohs(q->type) ) { + case RR_TYPE_NB: + q = (NBTNsResource *)AliasHandleResourceNB( + q, + pmax, + nbtarg + ); + break; + case RR_TYPE_A: + q = (NBTNsResource *)AliasHandleResourceA( + q, + pmax, + nbtarg + ); + break; + case RR_TYPE_NS: + q = (NBTNsResource *)AliasHandleResourceNS( + q, + pmax, + nbtarg + ); + break; + case RR_TYPE_NULL: + q = (NBTNsResource *)AliasHandleResourceNULL( + q, + pmax, + nbtarg + ); + break; + case RR_TYPE_NBSTAT: + q = (NBTNsResource *)AliasHandleResourceNBSTAT( + q, + pmax, + nbtarg + ); + break; + default: +#ifdef DEBUG + printf( + "\nUnknown Type of Resource %0x\n", + ntohs(q->type) + ); +#endif + break; + } + count--; + } + fflush(stdout); + return ((u_char *)q); +} + +int AliasHandleUdpNbtNS( + struct ip *pip, /* IP packet to examine/patch */ + struct alias_link *link, + struct in_addr *alias_address, + u_short *alias_port, + struct in_addr *original_address, + u_short *original_port ) +{ + struct udphdr * uh; + NbtNSHeader * nsh; + u_char * p; + char *pmax; + NBTArguments nbtarg; + + /* Set up Common Parameter */ + nbtarg.oldaddr = *alias_address; + nbtarg.oldport = *alias_port; + nbtarg.newaddr = *original_address; + nbtarg.newport = *original_port; + + /* Calculate data length of UDP packet */ + uh = (struct udphdr *) ((char *) pip + (pip->ip_hl << 2)); + nbtarg.uh_sum = &(uh->uh_sum); + nsh = (NbtNSHeader *)((char *)uh + (sizeof(struct udphdr))); + p = (u_char *)(nsh + 1); + pmax = (char *)uh + ntohs( uh->uh_ulen ); + + if ((char *)(nsh + 1) > pmax) + return(-1); + +#ifdef DEBUG + printf(" [%s] ID=%02x, op=%01x, flag=%02x, rcode=%01x, qd=%04x" + ", an=%04x, ns=%04x, ar=%04x, [%d]-->", + nsh->dir ? "Response": "Request", + nsh->nametrid, + nsh->opcode, + nsh->nmflags, + nsh->rcode, + ntohs(nsh->qdcount), + ntohs(nsh->ancount), + ntohs(nsh->nscount), + ntohs(nsh->arcount), + (u_char *)p -(u_char *)nsh + ); +#endif + + /* Question Entries */ + if (ntohs(nsh->qdcount) !=0 ) { + p = AliasHandleQuestion( + ntohs(nsh->qdcount), + (NBTNsQuestion *)p, + pmax, + &nbtarg + ); + } + + /* Answer Resource Records */ + if (ntohs(nsh->ancount) !=0 ) { + p = AliasHandleResource( + ntohs(nsh->ancount), + (NBTNsResource *)p, + pmax, + &nbtarg + ); + } + + /* Authority Resource Recodrs */ + if (ntohs(nsh->nscount) !=0 ) { + p = AliasHandleResource( + ntohs(nsh->nscount), + (NBTNsResource *)p, + pmax, + &nbtarg + ); + } + + /* Additional Resource Recodrs */ + if (ntohs(nsh->arcount) !=0 ) { + p = AliasHandleResource( + ntohs(nsh->arcount), + (NBTNsResource *)p, + pmax, + &nbtarg + ); + } + +#ifdef DEBUG + PrintRcode(nsh->rcode); +#endif + return ((p == NULL) ? -1 : 0); +} diff --git a/alias/alias_proxy.c b/alias/alias_proxy.c new file mode 100644 index 0000000..60437bf --- /dev/null +++ b/alias/alias_proxy.c @@ -0,0 +1,805 @@ +/* file: alias_proxy.c + + This file encapsulates special operations related to transparent + proxy redirection. This is where packets with a particular destination, + usually tcp port 80, are redirected to a proxy server. + + When packets are proxied, the destination address and port are + modified. In certain cases, it is necessary to somehow encode + the original address/port info into the packet. Two methods are + presently supported: addition of a [DEST addr port] string at the + beginning a of tcp stream, or inclusion of an optional field + in the IP header. + + There is one public API function: + + PacketAliasProxyRule() -- Adds and deletes proxy + rules. + + Rules are stored in a linear linked list, so lookup efficiency + won't be too good for large lists. + + + Initial development: April, 1998 (cjm) +*/ + + +/* System includes */ +#include +#include +#include +#include +#include + +#include +#include + +/* BSD IPV4 includes */ +#include +#include +#include +#include + +#include + +#include "alias_local.h" /* Functions used by alias*.c */ +#include "alias.h" /* Public API functions for libalias */ + + + +/* + Data structures + */ + +/* + * A linked list of arbitrary length, based on struct proxy_entry is + * used to store proxy rules. + */ +struct proxy_entry +{ +#define PROXY_TYPE_ENCODE_NONE 1 +#define PROXY_TYPE_ENCODE_TCPSTREAM 2 +#define PROXY_TYPE_ENCODE_IPHDR 3 + int rule_index; + int proxy_type; + u_char proto; + u_short proxy_port; + u_short server_port; + + struct in_addr server_addr; + + struct in_addr src_addr; + struct in_addr src_mask; + + struct in_addr dst_addr; + struct in_addr dst_mask; + + struct proxy_entry *next; + struct proxy_entry *last; +}; + + + +/* + File scope variables +*/ + +static struct proxy_entry *proxyList; + + + +/* Local (static) functions: + + IpMask() -- Utility function for creating IP + masks from integer (1-32) specification. + IpAddr() -- Utility function for converting string + to IP address + IpPort() -- Utility function for converting string + to port number + RuleAdd() -- Adds an element to the rule list. + RuleDelete() -- Removes an element from the rule list. + RuleNumberDelete() -- Removes all elements from the rule list + having a certain rule number. + ProxyEncodeTcpStream() -- Adds [DEST x.x.x.x xxxx] to the beginning + of a TCP stream. + ProxyEncodeIpHeader() -- Adds an IP option indicating the true + destination of a proxied IP packet +*/ + +static int IpMask(int, struct in_addr *); +static int IpAddr(char *, struct in_addr *); +static int IpPort(char *, int, int *); +static void RuleAdd(struct proxy_entry *); +static void RuleDelete(struct proxy_entry *); +static int RuleNumberDelete(int); +static void ProxyEncodeTcpStream(struct alias_link *, struct ip *, int); +static void ProxyEncodeIpHeader(struct ip *, int); + +static int +IpMask(int nbits, struct in_addr *mask) +{ + int i; + u_int imask; + + if (nbits < 0 || nbits > 32) + return -1; + + imask = 0; + for (i=0; i> 1) + 0x80000000; + mask->s_addr = htonl(imask); + + return 0; +} + +static int +IpAddr(char *s, struct in_addr *addr) +{ + if (inet_aton(s, addr) == 0) + return -1; + else + return 0; +} + +static int +IpPort(char *s, int proto, int *port) +{ + int n; + + n = sscanf(s, "%d", port); + if (n != 1) + { + struct servent *se; + + if (proto == IPPROTO_TCP) + se = getservbyname(s, "tcp"); + else if (proto == IPPROTO_UDP) + se = getservbyname(s, "udp"); + else + return -1; + + if (se == NULL) + return -1; + + *port = (u_int) ntohs(se->s_port); + } + + return 0; +} + +void +RuleAdd(struct proxy_entry *entry) +{ + int rule_index; + struct proxy_entry *ptr; + struct proxy_entry *ptr_last; + + if (proxyList == NULL) + { + proxyList = entry; + entry->last = NULL; + entry->next = NULL; + return; + } + + rule_index = entry->rule_index; + ptr = proxyList; + ptr_last = NULL; + while (ptr != NULL) + { + if (ptr->rule_index >= rule_index) + { + if (ptr_last == NULL) + { + entry->next = proxyList; + entry->last = NULL; + proxyList->last = entry; + proxyList = entry; + return; + } + + ptr_last->next = entry; + ptr->last = entry; + entry->last = ptr->last; + entry->next = ptr; + return; + } + ptr_last = ptr; + ptr = ptr->next; + } + + ptr_last->next = entry; + entry->last = ptr_last; + entry->next = NULL; +} + +static void +RuleDelete(struct proxy_entry *entry) +{ + if (entry->last != NULL) + entry->last->next = entry->next; + else + proxyList = entry->next; + + if (entry->next != NULL) + entry->next->last = entry->last; + + free(entry); +} + +static int +RuleNumberDelete(int rule_index) +{ + int err; + struct proxy_entry *ptr; + + err = -1; + ptr = proxyList; + while (ptr != NULL) + { + struct proxy_entry *ptr_next; + + ptr_next = ptr->next; + if (ptr->rule_index == rule_index) + { + err = 0; + RuleDelete(ptr); + } + + ptr = ptr_next; + } + + return err; +} + +static void +ProxyEncodeTcpStream(struct alias_link *link, + struct ip *pip, + int maxpacketsize) +{ + int slen; + char buffer[40]; + struct tcphdr *tc; + +/* Compute pointer to tcp header */ + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + +/* Don't modify if once already modified */ + + if (GetAckModified (link)) + return; + +/* Translate destination address and port to string form */ + snprintf(buffer, sizeof(buffer) - 2, "[DEST %s %d]", + inet_ntoa(GetProxyAddress (link)), (u_int) ntohs(GetProxyPort (link))); + +/* Pad string out to a multiple of two in length */ + slen = strlen(buffer); + switch (slen % 2) + { + case 0: + strcat(buffer, " \n"); + slen += 2; + break; + case 1: + strcat(buffer, "\n"); + slen += 1; + } + +/* Check for packet overflow */ + if ((ntohs(pip->ip_len) + strlen(buffer)) > maxpacketsize) + return; + +/* Shift existing TCP data and insert destination string */ + { + int dlen; + int hlen; + u_char *p; + + hlen = (pip->ip_hl + tc->th_off) << 2; + dlen = ntohs (pip->ip_len) - hlen; + +/* Modify first packet that has data in it */ + + if (dlen == 0) + return; + + p = (char *) pip; + p += hlen; + + memmove(p + slen, p, dlen); + memcpy(p, buffer, slen); + } + +/* Save information about modfied sequence number */ + { + int delta; + + SetAckModified(link); + delta = GetDeltaSeqOut(pip, link); + AddSeq(pip, link, delta+slen); + } + +/* Update IP header packet length and checksum */ + { + int accumulate; + + accumulate = pip->ip_len; + pip->ip_len = htons(ntohs(pip->ip_len) + slen); + accumulate -= pip->ip_len; + + ADJUST_CHECKSUM(accumulate, pip->ip_sum); + } + +/* Update TCP checksum, Use TcpChecksum since so many things have + already changed. */ + + tc->th_sum = 0; + tc->th_sum = TcpChecksum (pip); +} + +static void +ProxyEncodeIpHeader(struct ip *pip, + int maxpacketsize) +{ +#define OPTION_LEN_BYTES 8 +#define OPTION_LEN_INT16 4 +#define OPTION_LEN_INT32 2 + u_char option[OPTION_LEN_BYTES]; + +#ifdef DEBUG + fprintf(stdout, " ip cksum 1 = %x\n", (u_int) IpChecksum(pip)); + fprintf(stdout, "tcp cksum 1 = %x\n", (u_int) TcpChecksum(pip)); +#endif + +/* Check to see that there is room to add an IP option */ + if (pip->ip_hl > (0x0f - OPTION_LEN_INT32)) + return; + +/* Build option and copy into packet */ + { + u_char *ptr; + struct tcphdr *tc; + + ptr = (u_char *) pip; + ptr += 20; + memcpy(ptr + OPTION_LEN_BYTES, ptr, ntohs(pip->ip_len) - 20); + + option[0] = 0x64; /* class: 3 (reserved), option 4 */ + option[1] = OPTION_LEN_BYTES; + + memcpy(&option[2], (u_char *) &pip->ip_dst, 4); + + tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2)); + memcpy(&option[6], (u_char *) &tc->th_sport, 2); + + memcpy(ptr, option, 8); + } + +/* Update checksum, header length and packet length */ + { + int i; + int accumulate; + u_short *sptr; + + sptr = (u_short *) option; + accumulate = 0; + for (i=0; iip_hl += OPTION_LEN_INT32; + accumulate -= *sptr; + + accumulate += pip->ip_len; + pip->ip_len = htons(ntohs(pip->ip_len) + OPTION_LEN_BYTES); + accumulate -= pip->ip_len; + + ADJUST_CHECKSUM(accumulate, pip->ip_sum); + } +#undef OPTION_LEN_BYTES +#undef OPTION_LEN_INT16 +#undef OPTION_LEN_INT32 +#ifdef DEBUG + fprintf(stdout, " ip cksum 2 = %x\n", (u_int) IpChecksum(pip)); + fprintf(stdout, "tcp cksum 2 = %x\n", (u_int) TcpChecksum(pip)); +#endif +} + + +/* Functions by other packet alias source files + + ProxyCheck() -- Checks whether an outgoing packet should + be proxied. + ProxyModify() -- Encodes the original destination address/port + for a packet which is to be redirected to + a proxy server. +*/ + +int +ProxyCheck(struct ip *pip, + struct in_addr *proxy_server_addr, + u_short *proxy_server_port) +{ + u_short dst_port; + struct in_addr src_addr; + struct in_addr dst_addr; + struct proxy_entry *ptr; + + src_addr = pip->ip_src; + dst_addr = pip->ip_dst; + dst_port = ((struct tcphdr *) ((char *) pip + (pip->ip_hl << 2))) + ->th_dport; + + ptr = proxyList; + while (ptr != NULL) + { + u_short proxy_port; + + proxy_port = ptr->proxy_port; + if ((dst_port == proxy_port || proxy_port == 0) + && pip->ip_p == ptr->proto + && src_addr.s_addr != ptr->server_addr.s_addr) + { + struct in_addr src_addr_masked; + struct in_addr dst_addr_masked; + + src_addr_masked.s_addr = src_addr.s_addr & ptr->src_mask.s_addr; + dst_addr_masked.s_addr = dst_addr.s_addr & ptr->dst_mask.s_addr; + + if ((src_addr_masked.s_addr == ptr->src_addr.s_addr) + && (dst_addr_masked.s_addr == ptr->dst_addr.s_addr)) + { + if ((*proxy_server_port = ptr->server_port) == 0) + *proxy_server_port = dst_port; + *proxy_server_addr = ptr->server_addr; + return ptr->proxy_type; + } + } + ptr = ptr->next; + } + + return 0; +} + +void +ProxyModify(struct alias_link *link, + struct ip *pip, + int maxpacketsize, + int proxy_type) +{ + switch (proxy_type) + { + case PROXY_TYPE_ENCODE_IPHDR: + ProxyEncodeIpHeader(pip, maxpacketsize); + break; + + case PROXY_TYPE_ENCODE_TCPSTREAM: + ProxyEncodeTcpStream(link, pip, maxpacketsize); + break; + } +} + + +/* + Public API functions +*/ + +int +PacketAliasProxyRule(const char *cmd) +{ +/* + * This function takes command strings of the form: + * + * server [:] + * [port ] + * [rule n] + * [proto tcp|udp] + * [src [/n]] + * [dst [/n]] + * [type encode_tcp_stream|encode_ip_hdr|no_encode] + * + * delete + * + * Subfields can be in arbitrary order. Port numbers and addresses + * must be in either numeric or symbolic form. An optional rule number + * is used to control the order in which rules are searched. If two + * rules have the same number, then search order cannot be guaranteed, + * and the rules should be disjoint. If no rule number is specified, + * then 0 is used, and group 0 rules are always checked before any + * others. + */ + int i, n, len; + int cmd_len; + int token_count; + int state; + char *token; + char buffer[256]; + char str_port[sizeof(buffer)]; + char str_server_port[sizeof(buffer)]; + + int rule_index; + int proto; + int proxy_type; + int proxy_port; + int server_port; + struct in_addr server_addr; + struct in_addr src_addr, src_mask; + struct in_addr dst_addr, dst_mask; + struct proxy_entry *proxy_entry; + +/* Copy command line into a buffer */ + cmd_len = strlen(cmd); + if (cmd_len > (sizeof(buffer) - 1)) + return -1; + strcpy(buffer, cmd); + +/* Convert to lower case */ + len = strlen(buffer); + for (i=0; iproxy_type = proxy_type; + proxy_entry->rule_index = rule_index; + proxy_entry->proto = proto; + proxy_entry->proxy_port = htons(proxy_port); + proxy_entry->server_port = htons(server_port); + proxy_entry->server_addr = server_addr; + proxy_entry->src_addr.s_addr = src_addr.s_addr & src_mask.s_addr; + proxy_entry->dst_addr.s_addr = dst_addr.s_addr & dst_mask.s_addr; + proxy_entry->src_mask = src_mask; + proxy_entry->dst_mask = dst_mask; + + RuleAdd(proxy_entry); + + return 0; +} diff --git a/alias/alias_util.c b/alias/alias_util.c new file mode 100644 index 0000000..fe07653 --- /dev/null +++ b/alias/alias_util.c @@ -0,0 +1,137 @@ +/* + Alias_util.h contains general utilities used by other functions + in the packet aliasing module. At the moment, there are functions + for computing IP header and TCP packet checksums. + + The checksum routines are based upon example code in a Unix networking + text written by Stevens (sorry, I can't remember the title -- but + at least this is a good author). + + Initial Version: August, 1996 (cjm) + + Version 1.7: January 9, 1997 + Added differential checksum update function. +*/ + +/* +Note: the checksum routines assume that the actual checksum word has +been zeroed out. If the checksum workd is filled with the proper value, +then these routines will give a result of zero (useful for testing +purposes); +*/ + +#include +#include +#include +#include +#include + +#include "alias.h" +#include "alias_local.h" + +u_short +PacketAliasInternetChecksum(u_short *ptr, int nbytes) +{ + int sum, oddbyte; + + sum = 0; + while (nbytes > 1) + { + sum += *ptr++; + nbytes -= 2; + } + if (nbytes == 1) + { + oddbyte = 0; + *((u_char *) &oddbyte) = *(u_char *) ptr; + sum += oddbyte; + } + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return(~sum); +} + +u_short +IpChecksum(struct ip *pip) +{ + return( PacketAliasInternetChecksum((u_short *) pip, + (pip->ip_hl << 2)) ); + +} + +u_short +TcpChecksum(struct ip *pip) +{ + u_short *ptr; + struct tcphdr *tc; + int nhdr, ntcp, nbytes; + int sum, oddbyte; + + nhdr = pip->ip_hl << 2; + ntcp = ntohs(pip->ip_len) - nhdr; + + tc = (struct tcphdr *) ((char *) pip + nhdr); + ptr = (u_short *) tc; + +/* Add up TCP header and data */ + nbytes = ntcp; + sum = 0; + while (nbytes > 1) + { + sum += *ptr++; + nbytes -= 2; + } + if (nbytes == 1) + { + oddbyte = 0; + *((u_char *) &oddbyte) = *(u_char *) ptr; + sum += oddbyte; + } + +/* "Pseudo-header" data */ + ptr = (u_short *) &(pip->ip_dst); + sum += *ptr++; + sum += *ptr; + ptr = (u_short *) &(pip->ip_src); + sum += *ptr++; + sum += *ptr; + sum += htons((u_short) ntcp); + sum += htons((u_short) pip->ip_p); + +/* Roll over carry bits */ + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + +/* Return checksum */ + return((u_short) ~sum); +} + + +void +DifferentialChecksum(u_short *cksum, u_short *new, u_short *old, int n) +{ + int i; + int accumulate; + + accumulate = *cksum; + for (i=0; i> 16) + (accumulate & 0xffff); + accumulate += accumulate >> 16; + *cksum = (u_short) ~accumulate; + } + else + { + accumulate = (accumulate >> 16) + (accumulate & 0xffff); + accumulate += accumulate >> 16; + *cksum = (u_short) accumulate; + } +} + diff --git a/arp.tproj/Makefile b/arp.tproj/Makefile new file mode 100644 index 0000000..50e5151 --- /dev/null +++ b/arp.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = arp + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = arp.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble arp4.4 arp.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/arp.tproj/Makefile.postamble b/arp.tproj/Makefile.postamble new file mode 100644 index 0000000..3b11434 --- /dev/null +++ b/arp.tproj/Makefile.postamble @@ -0,0 +1,115 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. + +beforeinstall: + install -c -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} arp4.0 \ + ${DESTDIR}${MANDIR}4/arp.0 + diff --git a/arp.tproj/Makefile.preamble b/arp.tproj/Makefile.preamble new file mode 100644 index 0000000..c7802b8 --- /dev/null +++ b/arp.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +#OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = arp4.0 +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/arp.tproj/PB.project b/arp.tproj/PB.project new file mode 100644 index 0000000..237a43f --- /dev/null +++ b/arp.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (arp.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, arp4.4, arp.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = arp; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/arp.tproj/arp.8 b/arp.tproj/arp.8 new file mode 100644 index 0000000..313aba2 --- /dev/null +++ b/arp.tproj/arp.8 @@ -0,0 +1,122 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)arp.8 8.2 (Berkeley) 4/27/95 +.\" +.Dd April 27, 1995 +.Dt ARP 8 +.Os BSD 4.3 +.Sh NAME +.Nm arp +.Nd address resolution display and control +.Sh SYNOPSIS +.Nm arp +.Ar hostname +.Nm arp +.Fl a +.Nm arp +.Fl d Ar hostname +.Nm arp +.Fl s Ar hostname ether_addr +.Op Ar temp +.Op Ar pub +.Nm arp +.Fl f Ar filename +.Sh DESCRIPTION +The +.Nm arp +program displays and modifies the Internet-to-Ethernet address translation +tables used by the address resolution protocol +.Pq Xr arp 4 . +With no flags, the program displays the current +.Tn ARP +entry for +.Ar hostname . +The host may be specified by name or by number, +using Internet dot notation. +.Pp +Available options: +.Bl -tag -width Ds +.It Fl a +The program displays all of the current +.Tn ARP +entries. +.It Fl d +A super-user may delete an entry for the host called +.Ar hostname +with the +.Fl d +flag. +.It Fl s Ar hostname ether_addr +Create an +.Tn ARP +entry for the host called +.Ar hostname +with the Ethernet address +.Ar ether_addr . +The Ethernet address is given as six hex bytes separated by colons. +The entry will be permanent unless the word +.Ar temp +is given in the command. +If the word +.Ar pub +is given, the entry will be "published"; i.e., this system will +act as an +.Tn ARP +server, +responding to requests for +.Ar hostname +even though the host address is not its own. +.It Fl f +Causes the file +.Ar filename +to be read and multiple entries to be set in the +.Tn ARP +tables. Entries +in the file should be of the form +.Pp +.Bd -filled -offset indent -compact +.Ar hostname ether_addr +.Op Ar temp +.Op Ar pub +.Ed +.Pp +with argument meanings as given above. +.El +.Sh SEE ALSO +.Xr inet 3 , +.Xr arp 4 , +.Xr ifconfig 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/arp.tproj/arp.c b/arp.tproj/arp.c new file mode 100644 index 0000000..4e932b4 --- /dev/null +++ b/arp.tproj/arp.c @@ -0,0 +1,554 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1984, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Sun Microsystems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1984, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)arp.c 8.3 (Berkeley) 4/28/95"; +#endif /* not lint */ + +/* + * arp - display, set, and delete arp table entries + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int pid; +static int nflag; +static int s = -1; + +int delete __P((char *, char *)); +void dump __P((u_long)); +int ether_aton __P((char *, u_char *)); +void ether_print __P((u_char *)); +int file __P((char *)); +void get __P((char *)); +void getsocket __P((void)); +int rtmsg __P((int)); +int set __P((int, char **)); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char **argv; +{ + int ch; + + pid = getpid(); + while ((ch = getopt(argc, argv, "ands")) != EOF) + switch((char)ch) { + case 'a': + dump(0); + exit(0); + case 'd': + if (argc < 3 || argc > 4) + usage(); + delete(argv[2], argv[3]); + exit(0); + case 'n': + nflag = 1; + continue; + case 's': + if (argc < 4 || argc > 7) + usage(); + exit(set(argc-2, &argv[2]) ? 1 : 0); + case '?': + default: + usage(); + } + if (argc != 2) + usage(); + get(argv[1]); + return (0); +} + +/* + * Process a file to set standard arp entries + */ +int +file(name) + char *name; +{ + FILE *fp; + int i, retval; + char line[100], arg[5][50], *args[5]; + + if ((fp = fopen(name, "r")) == NULL) { + fprintf(stderr, "arp: cannot open %s\n", name); + exit(1); + } + args[0] = &arg[0][0]; + args[1] = &arg[1][0]; + args[2] = &arg[2][0]; + args[3] = &arg[3][0]; + args[4] = &arg[4][0]; + retval = 0; + while(fgets(line, 100, fp) != NULL) { + i = sscanf(line, "%s %s %s %s %s", arg[0], arg[1], arg[2], + arg[3], arg[4]); + if (i < 2) { + fprintf(stderr, "arp: bad line: %s\n", line); + retval = 1; + continue; + } + if (set(i, args)) + retval = 1; + } + fclose(fp); + return (retval); +} + +void +getsocket() { + if (s < 0) { + s = socket(PF_ROUTE, SOCK_RAW, 0); + if (s < 0) { + perror("arp: socket"); + exit(1); + } + } +} + +struct sockaddr_in so_mask = {8, 0, 0, { 0xffffffff}}; +struct sockaddr_inarp blank_sin = {sizeof(blank_sin), AF_INET }, sin_m; +struct sockaddr_dl blank_sdl = {sizeof(blank_sdl), AF_LINK }, sdl_m; +int expire_time, flags, export_only, doing_proxy, found_entry; +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; + +/* + * Set an individual arp entry + */ +int +set(argc, argv) + int argc; + char **argv; +{ + struct hostent *hp; + register struct sockaddr_inarp *sin = &sin_m; + register struct sockaddr_dl *sdl; + register struct rt_msghdr *rtm = &(m_rtmsg.m_rtm); + u_char *ea; + char *host = argv[0], *eaddr = argv[1]; + + getsocket(); + argc -= 2; + argv += 2; + sdl_m = blank_sdl; + sin_m = blank_sin; + sin->sin_addr.s_addr = inet_addr(host); + if (sin->sin_addr.s_addr == -1) { + if (!(hp = gethostbyname(host))) { + fprintf(stderr, "arp: %s: ", host); + herror((char *)NULL); + return (1); + } + bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, + sizeof sin->sin_addr); + } + ea = (u_char *)LLADDR(&sdl_m); + if (ether_aton(eaddr, ea) == 0) + sdl_m.sdl_alen = 6; + doing_proxy = flags = export_only = expire_time = 0; + while (argc-- > 0) { + if (strncmp(argv[0], "temp", 4) == 0) { + struct timeval time; + gettimeofday(&time, 0); + expire_time = time.tv_sec + 20 * 60; + } + else if (strncmp(argv[0], "pub", 3) == 0) { + flags |= RTF_ANNOUNCE; + doing_proxy = SIN_PROXY; + } else if (strncmp(argv[0], "trail", 5) == 0) { + printf("%s: Sending trailers is no longer supported\n", + host); + } + argv++; + } +tryagain: + if (rtmsg(RTM_GET) < 0) { + perror(host); + return (1); + } + sin = (struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); + if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { + if (sdl->sdl_family == AF_LINK && + (rtm->rtm_flags & RTF_LLINFO) && + !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { + case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: + case IFT_ISO88024: case IFT_ISO88025: + goto overwrite; + } + if (doing_proxy == 0) { + printf("set: can only proxy for %s\n", host); + return (1); + } + if (sin_m.sin_other & SIN_PROXY) { + printf("set: proxy entry exists for non 802 device\n"); + return(1); + } + sin_m.sin_other = SIN_PROXY; + export_only = 1; + goto tryagain; + } +overwrite: + if (sdl->sdl_family != AF_LINK) { + printf("cannot intuit interface index and type for %s\n", host); + return (1); + } + sdl_m.sdl_type = sdl->sdl_type; + sdl_m.sdl_index = sdl->sdl_index; + return (rtmsg(RTM_ADD)); +} + +/* + * Display an individual arp entry + */ +void +get(host) + char *host; +{ + struct hostent *hp; + struct sockaddr_inarp *sin = &sin_m; + + sin_m = blank_sin; + sin->sin_addr.s_addr = inet_addr(host); + if (sin->sin_addr.s_addr == -1) { + if (!(hp = gethostbyname(host))) { + fprintf(stderr, "arp: %s: ", host); + herror((char *)NULL); + exit(1); + } + bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, + sizeof sin->sin_addr); + } + dump(sin->sin_addr.s_addr); + if (found_entry == 0) { + printf("%s (%s) -- no entry\n", + host, inet_ntoa(sin->sin_addr)); + exit(1); + } +} + +/* + * Delete an arp entry + */ +int +delete(host, info) + char *host; + char *info; +{ + struct hostent *hp; + register struct sockaddr_inarp *sin = &sin_m; + register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; + struct sockaddr_dl *sdl; + + if (info && strncmp(info, "pro", 3) ) + export_only = 1; + getsocket(); + sin_m = blank_sin; + sin->sin_addr.s_addr = inet_addr(host); + if (sin->sin_addr.s_addr == -1) { + if (!(hp = gethostbyname(host))) { + fprintf(stderr, "arp: %s: ", host); + herror((char *)NULL); + return (1); + } + bcopy((char *)hp->h_addr, (char *)&sin->sin_addr, + sizeof sin->sin_addr); + } +tryagain: + if (rtmsg(RTM_GET) < 0) { + perror(host); + return (1); + } + sin = (struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)(sin->sin_len + (char *)sin); + if (sin->sin_addr.s_addr == sin_m.sin_addr.s_addr) { + if (sdl->sdl_family == AF_LINK && + (rtm->rtm_flags & RTF_LLINFO) && + !(rtm->rtm_flags & RTF_GATEWAY)) switch (sdl->sdl_type) { + case IFT_ETHER: case IFT_FDDI: case IFT_ISO88023: + case IFT_ISO88024: case IFT_ISO88025: + goto delete; + } + } + if (sin_m.sin_other & SIN_PROXY) { + fprintf(stderr, "delete: can't locate %s\n",host); + return (1); + } else { + sin_m.sin_other = SIN_PROXY; + goto tryagain; + } +delete: + if (sdl->sdl_family != AF_LINK) { + printf("cannot locate %s\n", host); + return (1); + } + if (rtmsg(RTM_DELETE)) + return (1); + printf("%s (%s) deleted\n", host, inet_ntoa(sin->sin_addr)); + return (0); +} + +/* + * Dump the entire arp table + */ +void +dump(addr) + u_long addr; +{ + int mib[6]; + size_t needed; + char *host, *lim, *buf, *next; + struct rt_msghdr *rtm; + struct sockaddr_inarp *sin; + struct sockaddr_dl *sdl; + extern int h_errno; + struct hostent *hp; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_FLAGS; + mib[5] = RTF_LLINFO; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + err(1, "route-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + err(1, "malloc"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + err(1, "actual retrieval of routing table"); + lim = buf + needed; + for (next = buf; next < lim; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)next; + sin = (struct sockaddr_inarp *)(rtm + 1); + sdl = (struct sockaddr_dl *)(sin + 1); + if (addr) { + if (addr != sin->sin_addr.s_addr) + continue; + found_entry = 1; + } + if (nflag == 0) + hp = gethostbyaddr((caddr_t)&(sin->sin_addr), + sizeof sin->sin_addr, AF_INET); + else + hp = 0; + if (hp) + host = hp->h_name; + else { + host = "?"; + if (h_errno == TRY_AGAIN) + nflag = 1; + } + printf("%s (%s) at ", host, inet_ntoa(sin->sin_addr)); + if (sdl->sdl_alen) + ether_print((u_char *)LLADDR(sdl)); + else + printf("(incomplete)"); + if (rtm->rtm_rmx.rmx_expire == 0) + printf(" permanent"); + if (sin->sin_other & SIN_PROXY) + printf(" published (proxy only)"); + if (rtm->rtm_addrs & RTA_NETMASK) { + sin = (struct sockaddr_inarp *) + (sdl->sdl_len + (char *)sdl); + if (sin->sin_addr.s_addr == 0xffffffff) + printf(" published"); + if (sin->sin_len != 8) + printf("(wierd)"); + } + printf("\n"); + } +} + +void +ether_print(cp) + u_char *cp; +{ + printf("%x:%x:%x:%x:%x:%x", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); +} + +int +ether_aton(a, n) + char *a; + u_char *n; +{ + int i, o[6]; + + i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o[0], &o[1], &o[2], + &o[3], &o[4], &o[5]); + if (i != 6) { + fprintf(stderr, "arp: invalid Ethernet address '%s'\n", a); + return (1); + } + for (i=0; i<6; i++) + n[i] = o[i]; + return (0); +} + +void +usage() +{ + printf("usage: arp hostname\n"); + printf(" arp -a [kernel] [kernel_memory]\n"); + printf(" arp -d hostname\n"); + printf(" arp -s hostname ether_addr [temp] [pub]\n"); + printf(" arp -f filename\n"); + exit(1); +} + +int +rtmsg(cmd) + int cmd; +{ + static int seq; + int rlen; + register struct rt_msghdr *rtm = &m_rtmsg.m_rtm; + register char *cp = m_rtmsg.m_space; + register int l; + + errno = 0; + if (cmd == RTM_DELETE) + goto doit; + bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); + rtm->rtm_flags = flags; + rtm->rtm_version = RTM_VERSION; + + switch (cmd) { + default: + fprintf(stderr, "arp: internal wrong cmd\n"); + exit(1); + case RTM_ADD: + rtm->rtm_addrs |= RTA_GATEWAY; + rtm->rtm_rmx.rmx_expire = expire_time; + rtm->rtm_inits = RTV_EXPIRE; + rtm->rtm_flags |= (RTF_HOST | RTF_STATIC); + sin_m.sin_other = 0; + if (doing_proxy) { + if (export_only) + sin_m.sin_other = SIN_PROXY; + else { + rtm->rtm_addrs |= RTA_NETMASK; + rtm->rtm_flags &= ~RTF_HOST; + } + } + /* FALLTHROUGH */ + case RTM_GET: + rtm->rtm_addrs |= RTA_DST; + } +#define NEXTADDR(w, s) \ + if (rtm->rtm_addrs & (w)) { \ + bcopy((char *)&s, cp, sizeof(s)); cp += sizeof(s);} + + NEXTADDR(RTA_DST, sin_m); + NEXTADDR(RTA_GATEWAY, sdl_m); + NEXTADDR(RTA_NETMASK, so_mask); + + rtm->rtm_msglen = cp - (char *)&m_rtmsg; +doit: + l = rtm->rtm_msglen; + rtm->rtm_seq = ++seq; + rtm->rtm_type = cmd; + if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { + if (errno != ESRCH || cmd != RTM_DELETE) { + perror("writing to routing socket"); + return (-1); + } + } + do { + l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); + } while (l > 0 && (rtm->rtm_seq != seq || rtm->rtm_pid != pid)); + if (l < 0) + (void) fprintf(stderr, "arp: read from routing socket: %s\n", + strerror(errno)); + return (0); +} diff --git a/arp.tproj/arp4.4 b/arp.tproj/arp4.4 new file mode 100644 index 0000000..0cd7161 --- /dev/null +++ b/arp.tproj/arp4.4 @@ -0,0 +1,124 @@ +.\" Copyright (c) 1985, 1986, 1988, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)arp4.4 6.5 (Berkeley) 4/18/94 +.\" +.Dd April 18, 1994 +.Dt ARP 4 +.Os BSD 4 +.Sh NAME +.Nm arp +.Nd Address Resolution Protocol +.Sh SYNOPSIS +.Em "pseudo-device ether" +.Sh DESCRIPTION +The Address Resolution Protocol (ARP) is a protocol used to dynamically +map between Internet host addresses and 10Mb/s Ethernet addresses. +It is used by all the 10Mb/s Ethernet interface drivers. +It is not specific to Internet protocols or to 10Mb/s Ethernet, +but this implementation currently supports only that combination. +.Pp +ARP caches Internet-Ethernet address mappings. +When an interface requests a mapping for an address not in the cache, +ARP queues the message which requires the mapping and broadcasts +a message on the associated network requesting the address mapping. +If a response is provided, the new mapping is cached and any pending +message is transmitted. +ARP will queue at most one packet while waiting for a response to a +mapping request; +only the most recently ``transmitted'' packet is kept. +If the target host does not respond after several requests, +the host is considered to be down for a short period (normally 20 seconds), +allowing an error to be returned to transmission attempts during this +interval. +The error is +.Li EHOSTDOWN +for a non-responding destination host, and +.Li EHOSTUNREACH +for a non-responding router. +.Pp +The ARP cache is stored in the system routing table as +dynamically-created host routes. +The route to a directly-attached Ethernet network is installed as a +.Dq cloning +route (one with the +.Li RTF_CLONING +flag set), +causing routes to individual hosts on that network to be created on +demand. +These routes time out periodically (normally 20 minutes after validated; +entries are not validated when not in use). +An entry for a host which is not responding is a +.Dq reject +route (one with the +.Li RTF_REJECT +flag set). +.Pp +ARP entries may be added, deleted or changed with the +.Xr arp 8 +utility. +Manually-added entries may be temporary or permanent, +and may be +.Dq published , +in which case the system will respond to ARP requests for that host +as if it were the target of the request. +.Pp +In the past, +ARP was used to negotiate the use of a trailer encapsulation. +This is no longer supported. +.Pp +ARP watches passively for hosts impersonating the local host (i.e. a host +which responds to an ARP mapping request for the local host's address). +.Sh DIAGNOSTICS +.Em "duplicate IP address %x!! sent from ethernet address: %x:%x:%x:%x:%x:%x." +ARP has discovered another host on the local network which responds to +mapping requests for its own Internet address with a different Ethernet +address, generally indicating that two hosts are attempting to use the +same Internet address. +.Sh SEE ALSO +.Xr inet 4 , +.Xr route 4 , +.Xr arp 8 , +.Xr ifconfig 8 , +.Xr route 8 +.sp +.Rs +.%A Plummer, D. +.%B "An Ethernet Address Resolution Protocol" +.%T RFC826 +.Re +.Rs +.%A Leffler, S.J. +.%A Karels, M.J. +.%B "Trailer Encapsulations +.%T RFC893 +.Re + diff --git a/bootparams/Makefile b/bootparams/Makefile new file mode 100644 index 0000000..8e40018 --- /dev/null +++ b/bootparams/Makefile @@ -0,0 +1,46 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = bootparams + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Aggregate + +TOOLS = bootparamd.tproj bpwhoami.tproj + +LIBRARIES = bootparams + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = aggregate.make +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/bootparams/Makefile.postamble b/bootparams/Makefile.postamble new file mode 100644 index 0000000..411cde6 --- /dev/null +++ b/bootparams/Makefile.postamble @@ -0,0 +1,100 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/bootparams/Makefile.preamble b/bootparams/Makefile.preamble new file mode 100644 index 0000000..0bf1e82 --- /dev/null +++ b/bootparams/Makefile.preamble @@ -0,0 +1,138 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' +OTHER_GARBAGE = *~ + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +# DSTROOT = $(HOME) diff --git a/bootparams/PB.project b/bootparams/PB.project new file mode 100644 index 0000000..631206a --- /dev/null +++ b/bootparams/PB.project @@ -0,0 +1,22 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + H_FILES = (); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + SUBPROJECTS = (bootparams, bootparamd.tproj, bpwhoami.tproj); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = bootparams; + PROJECTTYPE = Aggregate; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/bootparams/bootparamd.tproj/Makefile b/bootparams/bootparamd.tproj/Makefile new file mode 100644 index 0000000..ae0309c --- /dev/null +++ b/bootparams/bootparamd.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = bootparamd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = bootparamd.c bootparam_proc.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /Library/Executables +PDO_UNIX_INSTALLDIR = /bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/bootparams/bootparamd.tproj/Makefile.postamble b/bootparams/bootparamd.tproj/Makefile.postamble new file mode 100644 index 0000000..411cde6 --- /dev/null +++ b/bootparams/bootparamd.tproj/Makefile.postamble @@ -0,0 +1,100 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/bootparams/bootparamd.tproj/Makefile.preamble b/bootparams/bootparamd.tproj/Makefile.preamble new file mode 100644 index 0000000..db3f4e7 --- /dev/null +++ b/bootparams/bootparamd.tproj/Makefile.preamble @@ -0,0 +1,140 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' +OTHER_GARBAGE = *~ +OTHER_LIBS = -lbootparams + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +# DSTROOT = $(HOME) + diff --git a/bootparams/bootparamd.tproj/PB.project b/bootparams/bootparamd.tproj/PB.project new file mode 100644 index 0000000..89f2397 --- /dev/null +++ b/bootparams/bootparamd.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (bootparamd.c, bootparam_proc.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + SUBPROJECTS = (); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = bootparamd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Library/Executables; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/bootparams/bootparamd.tproj/bootparam_proc.c b/bootparams/bootparamd.tproj/bootparam_proc.c new file mode 100644 index 0000000..faa0ff3 --- /dev/null +++ b/bootparams/bootparamd.tproj/bootparam_proc.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * BOOTPARAMS server + * Copyright 1998, Apple Computer Inc. Unpublished. + * + * Written by Marc Majka + */ + +#include +#include "bootparam_prot.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int debug; +extern unsigned long route_addr; +extern char domain_name[]; + +struct hostent *h; +static char hostname[MAXHOSTNAMELEN]; + +bp_whoami_res * +bootparamproc_whoami_1_svc(whoami, req) +bp_whoami_arg *whoami; +struct svc_req *req; +{ + long haddr; + static bp_whoami_res res; + struct bootparamsent *bp; + + if (debug) + { + fprintf(stderr,"whoami %d.%d.%d.%d\n", + 255 & whoami->client_address.bp_address_u.ip_addr.net, + 255 & whoami->client_address.bp_address_u.ip_addr.host, + 255 & whoami->client_address.bp_address_u.ip_addr.lh, + 255 & whoami->client_address.bp_address_u.ip_addr.impno); + } + + bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, + (char *)&haddr, sizeof(haddr)); + h = gethostbyaddr((char *)&haddr, sizeof(haddr), AF_INET); + if (h == NULL) + { + if (debug) fprintf(stderr,"whoami failed: gethostbyaddr\n"); + return NULL; + } + + /* check whether subsequent bpgetfile requests would succeed */ + bp = bootparams_getbyname(h->h_name); + if (bp == NULL) { + if (debug) + fprintf(stderr, "whoami failed: bootparams_getbyname\n"); + return NULL; + } + + sprintf(hostname, "%s", h->h_name); + res.client_name = hostname; + + res.domain_name = domain_name; + + res.router_address.address_type = IP_ADDR_TYPE; + bcopy(&route_addr, &res.router_address.bp_address_u.ip_addr, 4); + + if (debug) + { + fprintf(stderr, "whoami name=%s domain=%s router=%d.%d.%d.%d\n", + res.client_name, + res.domain_name, + 255 & res.router_address.bp_address_u.ip_addr.net, + 255 & res.router_address.bp_address_u.ip_addr.host, + 255 & res.router_address.bp_address_u.ip_addr.lh, + 255 & res.router_address.bp_address_u.ip_addr.impno); + } + + return (&res); +} + +bp_getfile_res * +bootparamproc_getfile_1_svc(getfile, req) +bp_getfile_arg *getfile; +struct svc_req *req; +{ + static bp_getfile_res res; + struct bootparamsent *bp; + static char s[1024]; + char *p; + int i, len; + + if (debug) + { + fprintf(stderr, "getfile %s %s\n", + getfile->client_name, getfile->file_id); + } + + bp = bootparams_getbyname(getfile->client_name); + if (bp == NULL) + { + if (debug) + { + fprintf(stderr, "can't find bootparams for %s\n", + getfile->client_name); + fprintf(stderr, "getfile failed\n"); + } + return NULL; + } + + len = strlen(getfile->file_id) + 1; + sprintf(s, "%s=", getfile->file_id); + + for (i = 0; bp->bp_bootparams[i] != NULL; i++) + { + if (!strncmp(s, bp->bp_bootparams[i], len)) break; + } + + if (bp->bp_bootparams[i] == NULL) + { + if (debug) + { + fprintf(stderr, "can't find bootparam %s\n", getfile->file_id); + fprintf(stderr, "getfile failed\n"); + } + return NULL; + } + + sprintf(s, bp->bp_bootparams[i] + len); + p = strchr(s, ':'); + if (p == NULL) + { + hostname[0] = '\0'; + res.server_name = hostname; + res.server_address.bp_address_u.ip_addr.net = 0; + res.server_address.bp_address_u.ip_addr.host = 0; + res.server_address.bp_address_u.ip_addr.lh = 0; + res.server_address.bp_address_u.ip_addr.impno = 0; + res.server_address.address_type = 1; + res.server_path = s; + + if (debug) + { + fprintf(stderr, "getfile server=%s (%d.%d.%d.%d) path=%s\n", + res.server_name, + 255 & res.server_address.bp_address_u.ip_addr.net, + 255 & res.server_address.bp_address_u.ip_addr.host, + 255 & res.server_address.bp_address_u.ip_addr.lh, + 255 & res.server_address.bp_address_u.ip_addr.impno, + res.server_path); + } + return (&res); + } + + *p = '\0'; + p++; + h = gethostbyname(s); + if (h == NULL) + { + if (debug) + { + fprintf(stderr, "can't find server %s\n", s); + fprintf(stderr, "getfile failed\n"); + } + return NULL; + } + + res.server_name = s; + res.server_path = p; + bcopy(h->h_addr, &res.server_address.bp_address_u.ip_addr, h->h_length); + res.server_address.address_type = IP_ADDR_TYPE; + + if (debug) + { + fprintf(stderr, "getfile server=%s (%d.%d.%d.%d) path=%s\n", + res.server_name, + 255 & res.server_address.bp_address_u.ip_addr.net, + 255 & res.server_address.bp_address_u.ip_addr.host, + 255 & res.server_address.bp_address_u.ip_addr.lh, + 255 & res.server_address.bp_address_u.ip_addr.impno, + res.server_path); + } + + return (&res); +} diff --git a/bootparams/bootparamd.tproj/bootparamd.c b/bootparams/bootparamd.tproj/bootparamd.c new file mode 100644 index 0000000..e76bd42 --- /dev/null +++ b/bootparams/bootparamd.tproj/bootparamd.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * BOOTPARAMS server + * Copyright 1998, Apple Computer Inc. Unpublished. + * + * Written by Marc Majka + */ + +#include +#include +#include +#include +#include +#include "bootparam_prot.h" +#include +#include +#include +#include +#include +#include +#include + +int debug = 0; +char *progname; + +unsigned long route_addr; +char domain_name[MAXHOSTNAMELEN]; + +int _rpcsvcdirty; +extern void bootparamprog_1(); + +extern int getdomainname(char*, int); + +void +usage(void) +{ + fprintf(stderr, "usage: %s [-d] [-r router]\n", progname); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + SVCXPRT *transp; + int i; + struct hostent *h; + char str[256]; + FILE *fp; + + progname = strrchr(argv[0],'/'); + if (progname) progname++; + else progname = argv[0]; + + route_addr = 0; + + for (i = 1; i < argc; i++) + { + if (!strcmp(argv[i], "-d")) + { + debug = 1; + } + else if (!strcmp(argv[i], "-r")) + { + i++; + if (i >= argc) usage(); + + route_addr = inet_addr(argv[i]); + if (route_addr == -1) + { + h = gethostbyname(argv[i]); + if (h == NULL) + { + fprintf(stderr, "%s: Can't find host %s\n", + progname, argv[i]); + exit(1); + } + + bcopy(h->h_addr, (char *)&route_addr, sizeof(route_addr)); + } + } + else usage(); + } + + if (route_addr == 0) + { + fp = popen("/usr/sbin/netstat -r -n", "r"); + while (NULL != fgets(str, 256, fp)) + { + if (strncmp(str, "default ", 8)) continue; + if (!strncmp(str + 17, "link", 4)) continue; + route_addr = inet_addr(str+17); + break; + } + pclose(fp); + } + + domain_name[0] = '\0'; + if (getdomainname(domain_name, sizeof(domain_name)) != 0) + domain_name[0] = '\0'; + + if (debug == 0) daemon(0,0); + + openlog(progname, 0, LOG_DAEMON); + pmap_unset(BOOTPARAMPROG, BOOTPARAMVERS); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) + { + syslog(LOG_ERR, "Can't create udp service."); + exit(1); + } + + if (!svc_register(transp, BOOTPARAMPROG, BOOTPARAMVERS, bootparamprog_1, IPPROTO_UDP)) + { + syslog(LOG_ERR, "Can't register service."); + exit(1); + } + + svc_run(); + + syslog(LOG_ERR, "svc_run returned"); + exit(1); +} + + diff --git a/bootparams/bootparams/Makefile b/bootparams/bootparams/Makefile new file mode 100644 index 0000000..931d5c9 --- /dev/null +++ b/bootparams/bootparams/Makefile @@ -0,0 +1,52 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = bootparams + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Library + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ + bootparam_prot.x + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CURRENTLY_ACTIVE_VERSION = YES +DEPLOY_WITH_VERSION_NAME = A +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = library.make +NEXTSTEP_INSTALLDIR = /usr/local/lib +WINDOWS_INSTALLDIR = /Developer/Libraries +PDO_UNIX_INSTALLDIR = /lib +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +WINDOWS_PUBLIC_HEADERS_DIR = $(HOMEDRIVE)$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME) + +PDO_UNIX_PUBLIC_HEADERS_DIR = $(LOCAL_DEVELOPER_DIR)/Headers/$(NAME) + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/bootparams/bootparams/Makefile.postamble b/bootparams/bootparams/Makefile.postamble new file mode 100644 index 0000000..a939e58 --- /dev/null +++ b/bootparams/bootparams/Makefile.postamble @@ -0,0 +1,109 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Needed since a .x file in Other Sources will require a corresponding .o +%_xdr.c: %.x + $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x + +%_svc.c: %.x + $(RPCGEN) $(ALL_RPCFLAGS) -m -o $(SYM_DIR)/$*_svc.c $*.x + +after_install: + $(RM) -rf $(INSTALLED_PRODUCTS) diff --git a/bootparams/bootparams/Makefile.preamble b/bootparams/bootparams/Makefile.preamble new file mode 100644 index 0000000..9253661 --- /dev/null +++ b/bootparams/bootparams/Makefile.preamble @@ -0,0 +1,144 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. +AFTER_INSTALL = after_install + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +LIBRARY_STYLE = STATIC + +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' +OTHER_GARBAGE = *~ +OTHER_PROJECT_HEADERS = bootparam_prot.h +OTHER_OFILES = bootparam_prot_xdr.o bootparam_prot_svc.o + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +# DSTROOT = $(HOME) +-include ../../Makefile.include diff --git a/bootparams/bootparams/PB.project b/bootparams/bootparams/PB.project new file mode 100644 index 0000000..d753020 --- /dev/null +++ b/bootparams/bootparams/PB.project @@ -0,0 +1,30 @@ +{ + CURRENTLY_ACTIVE_VERSION = YES; + DEPLOY_WITH_VERSION_NAME = A; + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, bootparam_prot.x); + SUBPROJECTS = (); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/local/lib; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /lib; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PDO_UNIX_PUBLICHEADERSDIR = "$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)"; + PROJECTNAME = bootparams; + PROJECTTYPE = Library; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Developer/Libraries; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + WINDOWS_PUBLICHEADERSDIR = "$(HOMEDRIVE)$(LOCAL_DEVELOPER_DIR)/Headers/$(NAME)"; +} diff --git a/bootparams/bootparams/bootparam_prot.x b/bootparams/bootparams/bootparam_prot.x new file mode 100644 index 0000000..0339a81 --- /dev/null +++ b/bootparams/bootparams/bootparam_prot.x @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* @(#)bootparam_prot.x 2.1 88/08/01 4.0 RPCSRC */ +/* @(#)bootparam_prot.x 1.2 87/06/24 Copyr 1987 Sun Micro */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * RPC for bootparms service. + * There are two procedures: + * WHOAMI takes a net address and returns a client name and also a + * likely net address for routing + * GETFILE takes a client name and file identifier and returns the + * server name, server net address and pathname for the file. + * file identifiers typically include root, swap, pub and dump + */ + +#ifdef RPC_HDR +%#include +%#include +%#include +#endif + +const MAX_MACHINE_NAME = 255; +const MAX_PATH_LEN = 1024; +const MAX_FILEID = 32; +const IP_ADDR_TYPE = 1; + +typedef string bp_machine_name_t; +typedef string bp_path_t; +typedef string bp_fileid_t; + +struct ip_addr_t { + char net; + char host; + char lh; + char impno; +}; + +union bp_address switch (int address_type) { + case IP_ADDR_TYPE: + ip_addr_t ip_addr; +}; + +struct bp_whoami_arg { + bp_address client_address; +}; + +struct bp_whoami_res { + bp_machine_name_t client_name; + bp_machine_name_t domain_name; + bp_address router_address; +}; + +struct bp_getfile_arg { + bp_machine_name_t client_name; + bp_fileid_t file_id; +}; + +struct bp_getfile_res { + bp_machine_name_t server_name; + bp_address server_address; + bp_path_t server_path; +}; + +program BOOTPARAMPROG { + version BOOTPARAMVERS { + bp_whoami_res BOOTPARAMPROC_WHOAMI(bp_whoami_arg) = 1; + bp_getfile_res BOOTPARAMPROC_GETFILE(bp_getfile_arg) = 2; + } = 1; +} = 100026; diff --git a/bootparams/bpwhoami.tproj/Makefile b/bootparams/bpwhoami.tproj/Makefile new file mode 100644 index 0000000..1cf44ad --- /dev/null +++ b/bootparams/bpwhoami.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = bpwhoami + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = bpwhoami.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /Library/Executables +PDO_UNIX_INSTALLDIR = /bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/bootparams/bpwhoami.tproj/Makefile.postamble b/bootparams/bpwhoami.tproj/Makefile.postamble new file mode 100644 index 0000000..411cde6 --- /dev/null +++ b/bootparams/bpwhoami.tproj/Makefile.postamble @@ -0,0 +1,100 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/bootparams/bpwhoami.tproj/Makefile.preamble b/bootparams/bpwhoami.tproj/Makefile.preamble new file mode 100644 index 0000000..5a48598 --- /dev/null +++ b/bootparams/bpwhoami.tproj/Makefile.preamble @@ -0,0 +1,139 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' +OTHER_GARBAGE = *~ +OTHER_LIBS = -lbootparams + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +# DSTROOT = $(HOME) diff --git a/bootparams/bpwhoami.tproj/PB.project b/bootparams/bpwhoami.tproj/PB.project new file mode 100644 index 0000000..516c248 --- /dev/null +++ b/bootparams/bpwhoami.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (bpwhoami.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + SUBPROJECTS = (); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = bpwhoami; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Library/Executables; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/bootparams/bpwhoami.tproj/bpwhoami.c b/bootparams/bpwhoami.tproj/bpwhoami.c new file mode 100644 index 0000000..c846417 --- /dev/null +++ b/bootparams/bpwhoami.tproj/bpwhoami.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved + * + * bpwhoami.c + * - do a bootparams whoami call and echo the results to stdout + * + * The output is of the form: + * host_name= + * nis_domain= + * router= + * server_name= + * server_ip_address= + * + * The program will exit with the following codes: + * 0 Successfully retrieved info + * 1 RPC timed out while attempting to retrieve info + * 2 Unrecoverable error ie. don't bother trying to call again + * + * Modification History: + * Aug 5, 1997 Dieter Siegund (dieter@apple.com) + * - lifted code from the old hostname -AUTOMATIC- source + */ + + +#include + +#include +#include +#include +#include +#include + +void usage __P((void)); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "bootparam_prot.h" + +struct in_addr ip_address; +struct in_addr net_mask; + +static __inline__ +u_long iptohl(struct in_addr ip) +{ + return (ntohl(ip.s_addr)); +} + +static __inline__ boolean_t +in_subnet(struct in_addr netaddr, struct in_addr netmask, struct in_addr ip) +{ + if ((iptohl(ip) & iptohl(netmask)) + != (iptohl(netaddr) & iptohl(netmask))) { + return (FALSE); + } + return (TRUE); +} + +bool_t +each_whoresult(result, from) + bp_whoami_res *result; + struct sockaddr_in *from; +{ + if (result) { + struct hostent * host; + struct in_addr * router; + + /* + * guard against bogus router replies by making sure + * that the default router is on the same subnet + */ + router = (struct in_addr *) + &result->router_address.bp_address_u.ip_addr; + if (in_subnet(*router, net_mask, ip_address)) { + if (result->client_name && result->client_name[0]) + printf("host_name=%s\n", result->client_name); + if (result->domain_name && result->domain_name[0]) + printf("nis_domain=%s\n", result->domain_name); + printf("router=%s\n", inet_ntoa(*router)); + host = gethostbyaddr((char *) &from->sin_addr, + sizeof (from->sin_addr), AF_INET); + if (host) { + printf("server_name=%s\n", host->h_name); + } + printf("server_ip_address=%s\n", inet_ntoa(from->sin_addr)); + return(TRUE); + } + } + return(FALSE); +} + +#define MAX_IF 16 + +static boolean_t +getFirstInterface(struct ifreq * ret_p) +{ + struct ifconf ifconf; /* points to ifreq */ + struct ifreq * ifreq = NULL; + struct ifreq * ifrp; + int size = sizeof(struct ifreq) * MAX_IF; + int sockfd; + + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, "bpwhoami: socket call failed\n"); + return (FALSE); + } + + while (1) { + if (ifreq != NULL) + ifreq = (struct ifreq *)realloc(ifreq, size); + else + ifreq = (struct ifreq *)malloc(size); + + if (ifreq == NULL) + goto err; + + ifconf.ifc_len = size; + ifconf.ifc_req = ifreq; + if (ioctl(sockfd, SIOCGIFCONF, (caddr_t)&ifconf) < 0 + || ifconf.ifc_len <= 0) { + fprintf(stderr, "bpwhoami: ioctl SIOCGIFCONF failed\n"); + goto err; + } + if ((ifconf.ifc_len + sizeof(struct ifreq)) < size) + break; + size *= 2; + } +#define IFR_NEXT(ifr) \ + ((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \ + MAX(0, (int) (ifr)->ifr_addr.sa_len \ + - (int) sizeof((ifr)->ifr_addr)))) + for (ifrp = (struct ifreq *) ifconf.ifc_buf; + (char *) ifrp < &ifconf.ifc_buf[ifconf.ifc_len]; + ifrp = IFR_NEXT(ifrp)) { + if (ifrp->ifr_addr.sa_family == AF_INET) { + struct ifreq ifr; + + strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) + ; + else if ((ifr.ifr_flags & IFF_LOOPBACK) + || !(ifr.ifr_flags & IFF_UP)) + ; + else if (ioctl(sockfd, SIOCGIFNETMASK, (caddr_t)&ifr) < 0) + ; + else { + net_mask = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr; + *ret_p = *ifrp; + close(sockfd); + if (ifreq) + free(ifreq); + return (TRUE); + } + } + } + err: + close(sockfd); + if (ifreq) + free(ifreq); + return (FALSE); +} + +/* + * Routine: bp_whoami + * Function: + * Do a BOOTPARAMS WHOAMI RPC to find out hostname, domain, + * bootparams server, default router. + */ +int +bp_whoami() +{ + extern enum clnt_stat clnt_broadcast(); + struct ifreq ifr; + struct sockaddr_in *sockin; + enum clnt_stat stat; + struct bp_whoami_arg who_arg; + struct bp_whoami_res who_res; + + if (getFirstInterface(&ifr) == FALSE) + return (2); + + sockin = (struct sockaddr_in *) &ifr.ifr_addr; + ip_address = sockin->sin_addr; + who_arg.client_address.bp_address_u.ip_addr = + *((ip_addr_t *)&sockin->sin_addr); + who_arg.client_address.address_type = IP_ADDR_TYPE; + bzero(&who_res, sizeof (who_res)); + + /* + * Broadcast the whoami. + */ + stat = clnt_broadcast(BOOTPARAMPROG, BOOTPARAMVERS, + BOOTPARAMPROC_WHOAMI, xdr_bp_whoami_arg, + &who_arg, xdr_bp_whoami_res, &who_res, + each_whoresult); + + if (stat == RPC_SUCCESS) { + return (0); + } + if (stat == RPC_TIMEDOUT) + return (1); + fprintf(stderr, "bpwhoami: "); + clnt_perrno(stat); + return (2); +} + +int +main(argc,argv) + int argc; + char *argv[]; +{ + exit(bp_whoami()); +} diff --git a/domainname.tproj/Makefile b/domainname.tproj/Makefile new file mode 100644 index 0000000..12a1e35 --- /dev/null +++ b/domainname.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = domainname + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = domainname.c + +OTHERSRCS = Makefile.dist domainname.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /bin +WINDOWS_INSTALLDIR = /bin +PDO_UNIX_INSTALLDIR = /bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/domainname.tproj/Makefile.dist b/domainname.tproj/Makefile.dist new file mode 100644 index 0000000..755ae0d --- /dev/null +++ b/domainname.tproj/Makefile.dist @@ -0,0 +1,6 @@ +# from: @(#)Makefile 5.3 (Berkeley) 5/11/90 +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:57:38 wsanchez Exp $ + +PROG= domainname + +.include diff --git a/domainname.tproj/PB.project b/domainname.tproj/PB.project new file mode 100644 index 0000000..b16d0b9 --- /dev/null +++ b/domainname.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (domainname.c); + OTHER_SOURCES = (Makefile.dist, domainname.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = domainname; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/domainname.tproj/domainname.1 b/domainname.tproj/domainname.1 new file mode 100644 index 0000000..074bf43 --- /dev/null +++ b/domainname.tproj/domainname.1 @@ -0,0 +1,60 @@ +.\" Copyright (c) 1983, 1988, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)domainname.1 6.8 (Berkeley) 7/27/91 +.\" $Id: domainname.1,v 1.1.1.1 1999/05/02 03:57:38 wsanchez Exp $ +.\" +.Dd July 27, 1991 +.Dt DOMAINNAME 1 +.Os BSD 4.2 +.Sh NAME +.Nm domainname +.Nd set or print the name of the current domain +.Sh SYNOPSIS +.Nm domainname +.Op Ar name-of-domain +.Sh DESCRIPTION +.Nm Domainname +prints the domain name of the current host. The super-user can +set the domain name by supplying an argument; this is usually done in the +network initialization script +.Pa /etc/netstart , +normally run at boot +time. +.Sh SEE ALSO +.Xr hostname 1 , +.Xr getdomainname 2 , +.Xr setdomainname 2 +.Sh HISTORY +The +.Nm domainname +command appeared in +.Bx 4.2 . diff --git a/domainname.tproj/domainname.c b/domainname.tproj/domainname.c new file mode 100644 index 0000000..a229731 --- /dev/null +++ b/domainname.tproj/domainname.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992/3 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$Id: domainname.c,v 1.1.1.1 1999/05/02 03:57:38 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +static void usage __P((void)); + +main(argc, argv) + int argc; + char **argv; +{ + char dom[MAXHOSTNAMELEN]; + + if( argc>2 ) { + usage (); + /* NOTREACHED */ + } + + if( argc==2 ) { + if( setdomainname(argv[1], strlen(argv[1])+1) == -1) { + perror("setdomainname"); + exit(1); + } + } else { + if( getdomainname(dom, sizeof(dom)) == -1) { + perror("getdomainname"); + exit(1); + } + printf("%s\n", dom); + } + + exit(0); +} + +static void +usage () +{ + (void)fprintf(stderr, "usage: domainname [name-of-domain]\n"); + exit(1); +} diff --git a/ftp.tproj/Makefile b/ftp.tproj/Makefile new file mode 100644 index 0000000..980a8c2 --- /dev/null +++ b/ftp.tproj/Makefile @@ -0,0 +1,52 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ftp + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = extern.h ftp_var.h pathnames.h + +CFILES = cmds.c cmdtab.c domacro.c ftp.c ftp_var.c main.c\ + ruserpass.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ + h.template ftp.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ftp.tproj/Makefile.postamble b/ftp.tproj/Makefile.postamble new file mode 100644 index 0000000..7823726 --- /dev/null +++ b/ftp.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/ftp.tproj/Makefile.preamble b/ftp.tproj/Makefile.preamble new file mode 100644 index 0000000..74ce95a --- /dev/null +++ b/ftp.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/ftp.tproj/PB.project b/ftp.tproj/PB.project new file mode 100644 index 0000000..3b40ec2 --- /dev/null +++ b/ftp.tproj/PB.project @@ -0,0 +1,34 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (extern.h, ftp_var.h, pathnames.h); + OTHER_LINKED = (cmds.c, cmdtab.c, domacro.c, ftp.c, ftp_var.c, main.c, ruserpass.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + m.template, + h.template, + ftp.1 + ); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ftp; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ftp.tproj/cmds.c b/ftp.tproj/cmds.c new file mode 100644 index 0000000..6dd3f48 --- /dev/null +++ b/ftp.tproj/cmds.c @@ -0,0 +1,2236 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FTP User Program -- Command Routines. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ftp_var.h" +#include "pathnames.h" + +jmp_buf jabort; +char *mname; +char *home = "/"; + +/* + * `Another' gets another argument, and stores the new argc and argv. + * It reverts to the top level (via main.c's intr()) on EOF/error. + * + * Returns false if no new arguments have been added. + */ +int +another(pargc, pargv, prompt) + int *pargc; + char ***pargv; + char *prompt; +{ + int len = strlen(line), ret; + + if (len >= sizeof(line) - 3) { + printf("sorry, arguments too long\n"); + intr(); + } + printf("(%s) ", prompt); + line[len++] = ' '; + if (fgets(&line[len], sizeof(line) - len, stdin) == NULL) + intr(); + len += strlen(&line[len]); + if (len > 0 && line[len - 1] == '\n') + line[len - 1] = '\0'; + makeargv(); + ret = margc > *pargc; + *pargc = margc; + *pargv = margv; + return (ret); +} + +/* + * Connect to peer server and + * auto-login, if possible. + */ +void +setpeer(argc, argv) + int argc; + char *argv[]; +{ + char *host; + short port; + + if (connected) { + printf("Already connected to %s, use close first.\n", + hostname); + code = -1; + return; + } + if (argc < 2) + (void) another(&argc, &argv, "to"); + if (argc < 2 || argc > 3) { + printf("usage: %s host-name [port]\n", argv[0]); + code = -1; + return; + } + port = sp->s_port; + if (argc > 2) { + port = atoi(argv[2]); + if (port <= 0) { + printf("%s: bad port number-- %s\n", argv[1], argv[2]); + printf ("usage: %s host-name [port]\n", argv[0]); + code = -1; + return; + } + port = htons(port); + } + host = hookup(argv[1], port); + if (host) { + int overbose; + + connected = 1; + /* + * Set up defaults for FTP. + */ + (void) strcpy(typename, "ascii"), type = TYPE_A; + curtype = TYPE_A; + (void) strcpy(formname, "non-print"), form = FORM_N; + (void) strcpy(modename, "stream"), mode = MODE_S; + (void) strcpy(structname, "file"), stru = STRU_F; + (void) strcpy(bytename, "8"), bytesize = 8; + if (autologin) + (void) login(argv[1]); + +#if (defined(unix) || defined(__APPLE__)) && NBBY == 8 +/* + * this ifdef is to keep someone form "porting" this to an incompatible + * system and not checking this out. This way they have to think about it. + */ + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("SYST") == COMPLETE && overbose) { + char *cp, c; + cp = strchr(reply_string+4, ' '); + if (cp == NULL) + cp = strchr(reply_string+4, '\r'); + if (cp) { + if (cp[-1] == '.') + cp--; + c = *cp; + *cp = '\0'; + } + + printf("Remote system type is %s.\n", + reply_string+4); + if (cp) + *cp = c; + } + if (!strncmp(reply_string, "215 UNIX Type: L8", 17)) { + if (proxy) + unix_proxy = 1; + else + unix_server = 1; + /* + * Set type to 0 (not specified by user), + * meaning binary by default, but don't bother + * telling server. We can use binary + * for text files unless changed by the user. + */ + type = 0; + (void) strcpy(typename, "binary"); + if (overbose) + printf("Using %s mode to transfer files.\n", + typename); + } else { + if (proxy) + unix_proxy = 0; + else + unix_server = 0; + if (overbose && + !strncmp(reply_string, "215 TOPS20", 10)) + printf( +"Remember to set tenex mode when transfering binary files from this machine.\n"); + } + verbose = overbose; +#endif /* unix */ + } +} + +struct types { + char *t_name; + char *t_mode; + int t_type; + char *t_arg; +} types[] = { + { "ascii", "A", TYPE_A, 0 }, + { "binary", "I", TYPE_I, 0 }, + { "image", "I", TYPE_I, 0 }, + { "ebcdic", "E", TYPE_E, 0 }, + { "tenex", "L", TYPE_L, bytename }, + { NULL } +}; + +/* + * Set transfer type. + */ +void +settype(argc, argv) + int argc; + char *argv[]; +{ + struct types *p; + int comret; + + if (argc > 2) { + char *sep; + + printf("usage: %s [", argv[0]); + sep = " "; + for (p = types; p->t_name; p++) { + printf("%s%s", sep, p->t_name); + sep = " | "; + } + printf(" ]\n"); + code = -1; + return; + } + if (argc < 2) { + printf("Using %s mode to transfer files.\n", typename); + code = 0; + return; + } + for (p = types; p->t_name; p++) + if (strcmp(argv[1], p->t_name) == 0) + break; + if (p->t_name == 0) { + printf("%s: unknown mode\n", argv[1]); + code = -1; + return; + } + if ((p->t_arg != NULL) && (*(p->t_arg) != '\0')) + comret = command ("TYPE %s %s", p->t_mode, p->t_arg); + else + comret = command("TYPE %s", p->t_mode); + if (comret == COMPLETE) { + (void) strcpy(typename, p->t_name); + curtype = type = p->t_type; + } +} + +/* + * Internal form of settype; changes current type in use with server + * without changing our notion of the type for data transfers. + * Used to change to and from ascii for listings. + */ +void +changetype(newtype, show) + int newtype, show; +{ + struct types *p; + int comret, oldverbose = verbose; + + if (newtype == 0) + newtype = TYPE_I; + if (newtype == curtype) + return; + if (debug == 0 && show == 0) + verbose = 0; + for (p = types; p->t_name; p++) + if (newtype == p->t_type) + break; + if (p->t_name == 0) { + printf("ftp: internal error: unknown type %d\n", newtype); + return; + } + if (newtype == TYPE_L && bytename[0] != '\0') + comret = command("TYPE %s %s", p->t_mode, bytename); + else + comret = command("TYPE %s", p->t_mode); + if (comret == COMPLETE) + curtype = newtype; + verbose = oldverbose; +} + +char *stype[] = { + "type", + "", + 0 +}; + +/* + * Set binary transfer type. + */ +/*VARARGS*/ +void +setbinary(argc, argv) + int argc; + char **argv; +{ + + stype[1] = "binary"; + settype(2, stype); +} + +/* + * Set ascii transfer type. + */ +/*VARARGS*/ +void +setascii(argc, argv) + int argc; + char *argv[]; +{ + + stype[1] = "ascii"; + settype(2, stype); +} + +/* + * Set tenex transfer type. + */ +/*VARARGS*/ +void +settenex(argc, argv) + int argc; + char *argv[]; +{ + + stype[1] = "tenex"; + settype(2, stype); +} + +/* + * Set file transfer mode. + */ +/*ARGSUSED*/ +void +setftmode(argc, argv) + int argc; + char *argv[]; +{ + + printf("We only support %s mode, sorry.\n", modename); + code = -1; +} + +/* + * Set file transfer format. + */ +/*ARGSUSED*/ +void +setform(argc, argv) + int argc; + char *argv[]; +{ + + printf("We only support %s format, sorry.\n", formname); + code = -1; +} + +/* + * Set file transfer structure. + */ +/*ARGSUSED*/ +void +setstruct(argc, argv) + int argc; + char *argv[]; +{ + + printf("We only support %s structure, sorry.\n", structname); + code = -1; +} + +/* + * Send a single file. + */ +void +put(argc, argv) + int argc; + char *argv[]; +{ + char *cmd; + int loc = 0; + char *oldargv1, *oldargv2; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc < 2 && !another(&argc, &argv, "local-file")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "remote-file")) { +usage: + printf("usage: %s local-file remote-file\n", argv[0]); + code = -1; + return; + } + oldargv1 = argv[1]; + oldargv2 = argv[2]; + if (!globulize(&argv[1])) { + code = -1; + return; + } + /* + * If "globulize" modifies argv[1], and argv[2] is a copy of + * the old argv[1], make it a copy of the new argv[1]. + */ + if (argv[1] != oldargv1 && argv[2] == oldargv1) { + argv[2] = argv[1]; + } + cmd = (argv[0][0] == 'a') ? "APPE" : ((sunique) ? "STOU" : "STOR"); + if (loc && ntflag) { + argv[2] = dotrans(argv[2]); + } + if (loc && mapflag) { + argv[2] = domap(argv[2]); + } + sendrequest(cmd, argv[1], argv[2], + argv[1] != oldargv1 || argv[2] != oldargv2); +} + +/* + * Send multiple files. + */ +void +mput(argc, argv) + int argc; + char **argv; +{ + int i; + sig_t oldintr; + int ointer; + char *tp; + + if (argc < 2 && !another(&argc, &argv, "local-files")) { + printf("usage: %s local-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + if (proxy) { + char *cp, *tp2, tmpbuf[MAXPATHLEN]; + + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == 0) { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = cp; + tp2 = tmpbuf; + while ((*tp2 = *tp) != NULL) { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + } + tp = tmpbuf; + } + if (ntflag) { + tp = dotrans(tp); + } + if (mapflag) { + tp = domap(tp); + } + sendrequest((sunique) ? "STOU" : "STOR", + cp, tp, cp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } + (void) signal(SIGINT, oldintr); + mflag = 0; + return; + } + for (i = 1; i < argc; i++) { + char **cpp, **gargs; + glob_t gl; + int flags; + + if (!doglob) { + if (mflag && confirm(argv[0], argv[i])) { + tp = (ntflag) ? dotrans(argv[i]) : argv[i]; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + argv[i], tp, tp != argv[i] || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + continue; + } + + memset(&gl, 0, sizeof(gl)); + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + if (glob(argv[i], flags, NULL, &gl) || gl.gl_pathc == 0) { + warnx("%s: not found", argv[i]); + globfree(&gl); + continue; + } + for (cpp = gl.gl_pathv; cpp && *cpp != NULL; cpp++) { + if (mflag && confirm(argv[0], *cpp)) { + tp = (ntflag) ? dotrans(*cpp) : *cpp; + tp = (mapflag) ? domap(tp) : tp; + sendrequest((sunique) ? "STOU" : "STOR", + *cpp, tp, *cpp != tp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mput")) { + mflag++; + } + interactive = ointer; + } + } + } + globfree(&gl); + } + (void) signal(SIGINT, oldintr); + mflag = 0; +} + +void +reget(argc, argv) + int argc; + char *argv[]; +{ + + (void) getit(argc, argv, 1, "r+w"); +} + +void +get(argc, argv) + int argc; + char *argv[]; +{ + + (void) getit(argc, argv, 0, restart_point ? "r+w" : "w" ); +} + +/* + * Receive one file. + */ +int +getit(argc, argv, restartit, mode) + int argc; + char *argv[]; + char *mode; + int restartit; +{ + int loc = 0; + char *oldargv1, *oldargv2; + + if (argc == 2) { + argc++; + argv[2] = argv[1]; + loc++; + } + if (argc < 2 && !another(&argc, &argv, "remote-file")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "local-file")) { +usage: + printf("usage: %s remote-file [ local-file ]\n", argv[0]); + code = -1; + return (0); + } + oldargv1 = argv[1]; + oldargv2 = argv[2]; + if (!globulize(&argv[2])) { + code = -1; + return (0); + } + if (loc && mcase) { + char *tp = argv[1], *tp2, tmpbuf[MAXPATHLEN]; + + while (*tp && !islower(*tp)) { + tp++; + } + if (!*tp) { + tp = argv[2]; + tp2 = tmpbuf; + while ((*tp2 = *tp) != NULL) { + if (isupper(*tp2)) { + *tp2 = 'a' + *tp2 - 'A'; + } + tp++; + tp2++; + } + argv[2] = tmpbuf; + } + } + if (loc && ntflag) + argv[2] = dotrans(argv[2]); + if (loc && mapflag) + argv[2] = domap(argv[2]); + if (restartit) { + struct stat stbuf; + int ret; + + ret = stat(argv[2], &stbuf); + if (restartit == 1) { + if (ret < 0) { + warn("local: %s", argv[2]); + return (0); + } + restart_point = stbuf.st_size; + } else { + if (ret == 0) { + int overbose; + + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("MDTM %s", argv[1]) == COMPLETE) { + int yy, mo, day, hour, min, sec; + struct tm *tm; + verbose = overbose; + sscanf(reply_string, + "%*s %04d%02d%02d%02d%02d%02d", + &yy, &mo, &day, &hour, &min, &sec); + tm = gmtime(&stbuf.st_mtime); + tm->tm_mon++; + if (tm->tm_year > yy%100) + return (1); + if ((tm->tm_year == yy%100 && + tm->tm_mon > mo) || + (tm->tm_mon == mo && + tm->tm_mday > day) || + (tm->tm_mday == day && + tm->tm_hour > hour) || + (tm->tm_hour == hour && + tm->tm_min > min) || + (tm->tm_min == min && + tm->tm_sec > sec)) + return (1); + } else { + printf("%s\n", reply_string); + verbose = overbose; + return (0); + } + } + } + } + + recvrequest("RETR", argv[2], argv[1], mode, + argv[1] != oldargv1 || argv[2] != oldargv2); + restart_point = 0; + return (0); +} + +/* ARGSUSED */ +void +mabort(signo) + int signo; +{ + int ointer; + + printf("\n"); + (void) fflush(stdout); + if (mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", mname)) { + interactive = ointer; + longjmp(jabort,0); + } + interactive = ointer; + } + mflag = 0; + longjmp(jabort,0); +} + +/* + * Get multiple files. + */ +void +mget(argc, argv) + int argc; + char **argv; +{ + sig_t oldintr; + int ch, ointer; + char *cp, *tp, *tp2, tmpbuf[MAXPATHLEN]; + + if (argc < 2 && !another(&argc, &argv, "remote-files")) { + printf("usage: %s remote-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + while ((cp = remglob(argv,proxy)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + tp = cp; + if (mcase) { + for (tp2 = tmpbuf; ch = *tp++;) + *tp2++ = isupper(ch) ? tolower(ch) : ch; + tp = tmpbuf; + } + if (ntflag) { + tp = dotrans(tp); + } + if (mapflag) { + tp = domap(tp); + } + recvrequest("RETR", tp, cp, "w", + tp != cp || !interactive); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with","mget")) { + mflag++; + } + interactive = ointer; + } + } + } + (void) signal(SIGINT,oldintr); + mflag = 0; +} + +char * +remglob(argv,doswitch) + char *argv[]; + int doswitch; +{ + char temp[16]; + static char buf[MAXPATHLEN]; + static FILE *ftemp = NULL; + static char **args; + int oldverbose, oldhash; + char *cp, *mode; + + if (!mflag) { + if (!doglob) { + args = NULL; + } + else { + if (ftemp) { + (void) fclose(ftemp); + ftemp = NULL; + } + } + return (NULL); + } + if (!doglob) { + if (args == NULL) + args = argv; + if ((cp = *++args) == NULL) + args = NULL; + return (cp); + } + if (ftemp == NULL) { + (void) strcpy(temp, _PATH_TMP); + (void) mktemp(temp); + oldverbose = verbose, verbose = 0; + oldhash = hash, hash = 0; + if (doswitch) { + pswitch(!proxy); + } + for (mode = "w"; *++argv != NULL; mode = "a") + recvrequest ("NLST", temp, *argv, mode, 0); + if (doswitch) { + pswitch(!proxy); + } + verbose = oldverbose; hash = oldhash; + ftemp = fopen(temp, "r"); + (void) unlink(temp); + if (ftemp == NULL) { + printf("can't find list of remote files, oops\n"); + return (NULL); + } + } + if (fgets(buf, sizeof (buf), ftemp) == NULL) { + (void) fclose(ftemp), ftemp = NULL; + return (NULL); + } + if ((cp = strchr(buf, '\n')) != NULL) + *cp = '\0'; + return (buf); +} + +char * +onoff(bool) + int bool; +{ + + return (bool ? "on" : "off"); +} + +/* + * Show status. + */ +/*ARGSUSED*/ +void +status(argc, argv) + int argc; + char *argv[]; +{ + int i; + + if (connected) + printf("Connected to %s.\n", hostname); + else + printf("Not connected.\n"); + if (!proxy) { + pswitch(1); + if (connected) { + printf("Connected for proxy commands to %s.\n", hostname); + } + else { + printf("No proxy connection.\n"); + } + pswitch(0); + } + printf("Mode: %s; Type: %s; Form: %s; Structure: %s\n", + modename, typename, formname, structname); + printf("Verbose: %s; Bell: %s; Prompting: %s; Globbing: %s\n", + onoff(verbose), onoff(bell), onoff(interactive), + onoff(doglob)); + printf("Store unique: %s; Receive unique: %s\n", onoff(sunique), + onoff(runique)); + printf("Case: %s; CR stripping: %s\n",onoff(mcase),onoff(crflag)); + if (ntflag) { + printf("Ntrans: (in) %s (out) %s\n", ntin,ntout); + } + else { + printf("Ntrans: off\n"); + } + if (mapflag) { + printf("Nmap: (in) %s (out) %s\n", mapin, mapout); + } + else { + printf("Nmap: off\n"); + } + printf("Hash mark printing: %s; Use of PORT cmds: %s\n", + onoff(hash), onoff(sendport)); + if (macnum > 0) { + printf("Macros:\n"); + for (i=0; i 1) { + val = atoi(argv[1]); + if (val < 0) { + printf("%s: bad debugging value.\n", argv[1]); + code = -1; + return; + } + } else + val = !debug; + debug = val; + if (debug) + options |= SO_DEBUG; + else + options &= ~SO_DEBUG; + printf("Debugging %s (debug=%d).\n", onoff(debug), debug); + code = debug > 0; +} + +/* + * Set current working directory + * on remote machine. + */ +void +cd(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "remote-directory")) { + printf("usage: %s remote-directory\n", argv[0]); + code = -1; + return; + } + if (command("CWD %s", argv[1]) == ERROR && code == 500) { + if (verbose) + printf("CWD command not recognized, trying XCWD\n"); + (void) command("XCWD %s", argv[1]); + } +} + +/* + * Set current working directory + * on local machine. + */ +void +lcd(argc, argv) + int argc; + char *argv[]; +{ + char buf[MAXPATHLEN]; + + if (argc < 2) + argc++, argv[1] = home; + if (argc != 2) { + printf("usage: %s local-directory\n", argv[0]); + code = -1; + return; + } + if (!globulize(&argv[1])) { + code = -1; + return; + } + if (chdir(argv[1]) < 0) { + warn("local: %s", argv[1]); + code = -1; + return; + } + if (getwd(buf) != NULL) + printf("Local directory now %s\n", buf); + else + warnx("getwd: %s", buf); + code = 0; +} + +/* + * Delete a single file. + */ +void +delete(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "remote-file")) { + printf("usage: %s remote-file\n", argv[0]); + code = -1; + return; + } + (void) command("DELE %s", argv[1]); +} + +/* + * Delete multiple files. + */ +void +mdelete(argc, argv) + int argc; + char **argv; +{ + sig_t oldintr; + int ointer; + char *cp; + + if (argc < 2 && !another(&argc, &argv, "remote-files")) { + printf("usage: %s remote-files\n", argv[0]); + code = -1; + return; + } + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + while ((cp = remglob(argv,0)) != NULL) { + if (*cp == '\0') { + mflag = 0; + continue; + } + if (mflag && confirm(argv[0], cp)) { + (void) command("DELE %s", cp); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", "mdelete")) { + mflag++; + } + interactive = ointer; + } + } + } + (void) signal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Rename a remote file. + */ +void +renamefile(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "from-name")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "to-name")) { +usage: + printf("%s from-name to-name\n", argv[0]); + code = -1; + return; + } + if (command("RNFR %s", argv[1]) == CONTINUE) + (void) command("RNTO %s", argv[2]); +} + +/* + * Get a directory listing + * of remote files. + */ +void +ls(argc, argv) + int argc; + char *argv[]; +{ + char *cmd; + + if (argc < 2) + argc++, argv[1] = NULL; + if (argc < 3) + argc++, argv[2] = "-"; + if (argc > 3) { + printf("usage: %s remote-directory local-file\n", argv[0]); + code = -1; + return; + } + cmd = argv[0][0] == 'n' ? "NLST" : "LIST"; + if (strcmp(argv[2], "-") && !globulize(&argv[2])) { + code = -1; + return; + } + if (strcmp(argv[2], "-") && *argv[2] != '|') + if (!globulize(&argv[2]) || !confirm("output to local-file:", argv[2])) { + code = -1; + return; + } + recvrequest(cmd, argv[2], argv[1], "w", 0); +} + +/* + * Get a directory listing + * of multiple remote files. + */ +void +mls(argc, argv) + int argc; + char **argv; +{ + sig_t oldintr; + int ointer, i; + char *cmd, mode[1], *dest; + + if (argc < 2 && !another(&argc, &argv, "remote-files")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "local-file")) { +usage: + printf("usage: %s remote-files local-file\n", argv[0]); + code = -1; + return; + } + dest = argv[argc - 1]; + argv[argc - 1] = NULL; + if (strcmp(dest, "-") && *dest != '|') + if (!globulize(&dest) || + !confirm("output to local-file:", dest)) { + code = -1; + return; + } + cmd = argv[0][1] == 'l' ? "NLST" : "LIST"; + mname = argv[0]; + mflag = 1; + oldintr = signal(SIGINT, mabort); + (void) setjmp(jabort); + for (i = 1; mflag && i < argc-1; ++i) { + *mode = (i == 1) ? 'w' : 'a'; + recvrequest(cmd, dest, argv[i], mode, 0); + if (!mflag && fromatty) { + ointer = interactive; + interactive = 1; + if (confirm("Continue with", argv[0])) { + mflag ++; + } + interactive = ointer; + } + } + (void) signal(SIGINT, oldintr); + mflag = 0; +} + +/* + * Do a shell escape + */ +/*ARGSUSED*/ +void +shell(argc, argv) + int argc; + char **argv; +{ + pid_t pid; + sig_t old1, old2; + char shellnam[40], *shell, *namep; + union wait status; + + old1 = signal (SIGINT, SIG_IGN); + old2 = signal (SIGQUIT, SIG_IGN); + if ((pid = fork()) == 0) { + for (pid = 3; pid < 20; pid++) + (void) close(pid); + (void) signal(SIGINT, SIG_DFL); + (void) signal(SIGQUIT, SIG_DFL); + shell = getenv("SHELL"); + if (shell == NULL) + shell = _PATH_BSHELL; + namep = strrchr(shell,'/'); + if (namep == NULL) + namep = shell; + (void) strcpy(shellnam,"-"); + (void) strcat(shellnam, ++namep); + if (strcmp(namep, "sh") != 0) + shellnam[0] = '+'; + if (debug) { + printf ("%s\n", shell); + (void) fflush (stdout); + } + if (argc > 1) { + execl(shell,shellnam,"-c",altarg,(char *)0); + } + else { + execl(shell,shellnam,(char *)0); + } + warn("%s", shell); + code = -1; + exit(1); + } + if (pid > 0) + while (wait((int *)&status) != pid) + ; + (void) signal(SIGINT, old1); + (void) signal(SIGQUIT, old2); + if (pid == -1) { + warn("%s", "Try again later"); + code = -1; + } + else { + code = 0; + } +} + +/* + * Send new user information (re-login) + */ +void +user(argc, argv) + int argc; + char **argv; +{ + char acct[80]; + int n, aflag = 0; + + if (argc < 2) + (void) another(&argc, &argv, "username"); + if (argc < 2 || argc > 4) { + printf("usage: %s username [password] [account]\n", argv[0]); + code = -1; + return; + } + n = command("USER %s", argv[1]); + if (n == CONTINUE) { + if (argc < 3 ) + argv[2] = getpass("Password: "), argc++; + n = command("PASS %s", argv[2]); + } + if (n == CONTINUE) { + if (argc < 4) { + printf("Account: "); (void) fflush(stdout); + (void) fgets(acct, sizeof(acct) - 1, stdin); + acct[strlen(acct) - 1] = '\0'; + argv[3] = acct; argc++; + } + n = command("ACCT %s", argv[3]); + aflag++; + } + if (n != COMPLETE) { + fprintf(stdout, "Login failed.\n"); + return; + } + if (!aflag && argc == 4) { + (void) command("ACCT %s", argv[3]); + } +} + +/* + * Print working directory. + */ +/*VARARGS*/ +void +pwd(argc, argv) + int argc; + char *argv[]; +{ + int oldverbose = verbose; + + /* + * If we aren't verbose, this doesn't do anything! + */ + verbose = 1; + if (command("PWD") == ERROR && code == 500) { + printf("PWD command not recognized, trying XPWD\n"); + (void) command("XPWD"); + } + verbose = oldverbose; +} + +/* + * Make a directory. + */ +void +makedir(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "directory-name")) { + printf("usage: %s directory-name\n", argv[0]); + code = -1; + return; + } + if (command("MKD %s", argv[1]) == ERROR && code == 500) { + if (verbose) + printf("MKD command not recognized, trying XMKD\n"); + (void) command("XMKD %s", argv[1]); + } +} + +/* + * Remove a directory. + */ +void +removedir(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "directory-name")) { + printf("usage: %s directory-name\n", argv[0]); + code = -1; + return; + } + if (command("RMD %s", argv[1]) == ERROR && code == 500) { + if (verbose) + printf("RMD command not recognized, trying XRMD\n"); + (void) command("XRMD %s", argv[1]); + } +} + +/* + * Send a line, verbatim, to the remote machine. + */ +void +quote(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "command line to send")) { + printf("usage: %s line-to-send\n", argv[0]); + code = -1; + return; + } + quote1("", argc, argv); +} + +/* + * Send a SITE command to the remote machine. The line + * is sent verbatim to the remote machine, except that the + * word "SITE" is added at the front. + */ +void +site(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "arguments to SITE command")) { + printf("usage: %s line-to-send\n", argv[0]); + code = -1; + return; + } + quote1("SITE ", argc, argv); +} + +/* + * Turn argv[1..argc) into a space-separated string, then prepend initial text. + * Send the result as a one-line command and get response. + */ +void +quote1(initial, argc, argv) + char *initial; + int argc; + char **argv; +{ + int i, len; + char buf[BUFSIZ]; /* must be >= sizeof(line) */ + + (void) strcpy(buf, initial); + if (argc > 1) { + len = strlen(buf); + len += strlen(strcpy(&buf[len], argv[1])); + for (i = 2; i < argc; i++) { + buf[len++] = ' '; + len += strlen(strcpy(&buf[len], argv[i])); + } + } + if (command(buf) == PRELIM) { + while (getreply(0) == PRELIM) + continue; + } +} + +void +do_chmod(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "mode")) + goto usage; + if (argc < 3 && !another(&argc, &argv, "file-name")) { +usage: + printf("usage: %s mode file-name\n", argv[0]); + code = -1; + return; + } + (void) command("SITE CHMOD %s %s", argv[1], argv[2]); +} + +void +do_umask(argc, argv) + int argc; + char *argv[]; +{ + int oldverbose = verbose; + + verbose = 1; + (void) command(argc == 1 ? "SITE UMASK" : "SITE UMASK %s", argv[1]); + verbose = oldverbose; +} + +void +idle(argc, argv) + int argc; + char *argv[]; +{ + int oldverbose = verbose; + + verbose = 1; + (void) command(argc == 1 ? "SITE IDLE" : "SITE IDLE %s", argv[1]); + verbose = oldverbose; +} + +/* + * Ask the other side for help. + */ +void +rmthelp(argc, argv) + int argc; + char *argv[]; +{ + int oldverbose = verbose; + + verbose = 1; + (void) command(argc == 1 ? "HELP" : "HELP %s", argv[1]); + verbose = oldverbose; +} + +/* + * Terminate session and exit. + */ +/*VARARGS*/ +void +quit(argc, argv) + int argc; + char *argv[]; +{ + + if (connected) + disconnect(0, 0); + pswitch(1); + if (connected) { + disconnect(0, 0); + } + exit(0); +} + +/* + * Terminate session, but don't exit. + */ +void +disconnect(argc, argv) + int argc; + char *argv[]; +{ + + if (!connected) + return; + (void) command("QUIT"); + if (cout) { + (void) fclose(cout); + } + cout = NULL; + connected = 0; + data = -1; + if (!proxy) { + macnum = 0; + } +} + +int +confirm(cmd, file) + char *cmd, *file; +{ + char line[BUFSIZ]; + + if (!interactive) + return (1); + printf("%s %s? ", cmd, file); + (void) fflush(stdout); + if (fgets(line, sizeof line, stdin) == NULL) + return (0); + return (*line != 'n' && *line != 'N'); +} + +void +fatal(msg) + char *msg; +{ + + errx(1, "%s", msg); +} + +/* + * Glob a local file name specification with + * the expectation of a single return value. + * Can't control multiple values being expanded + * from the expression, we return only the first. + */ +int +globulize(cpp) + char **cpp; +{ + glob_t gl; + int flags; + + if (!doglob) + return (1); + + flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + memset(&gl, 0, sizeof(gl)); + if (glob(*cpp, flags, NULL, &gl) || + gl.gl_pathc == 0) { + warnx("%s: not found", *cpp); + globfree(&gl); + return (0); + } + *cpp = strdup(gl.gl_pathv[0]); /* XXX - wasted memory */ + globfree(&gl); + return (1); +} + +void +account(argc,argv) + int argc; + char **argv; +{ + char acct[50], *ap; + + if (argc > 1) { + ++argv; + --argc; + (void) strncpy(acct,*argv,49); + acct[49] = '\0'; + while (argc > 1) { + --argc; + ++argv; + (void) strncat(acct,*argv, 49-strlen(acct)); + } + ap = acct; + } + else { + ap = getpass("Account:"); + } + (void) command("ACCT %s", ap); +} + +jmp_buf abortprox; + +void +proxabort() +{ + + if (!proxy) { + pswitch(1); + } + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + longjmp(abortprox,1); +} + +void +doproxy(argc, argv) + int argc; + char *argv[]; +{ + struct cmd *c; + sig_t oldintr; + + if (argc < 2 && !another(&argc, &argv, "command")) { + printf("usage: %s command\n", argv[0]); + code = -1; + return; + } + c = getcmd(argv[1]); + if (c == (struct cmd *) -1) { + printf("?Ambiguous command\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (c == 0) { + printf("?Invalid command\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (!c->c_proxy) { + printf("?Invalid proxy command\n"); + (void) fflush(stdout); + code = -1; + return; + } + if (setjmp(abortprox)) { + code = -1; + return; + } + oldintr = signal(SIGINT, proxabort); + pswitch(1); + if (c->c_conn && !connected) { + printf("Not connected\n"); + (void) fflush(stdout); + pswitch(0); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + (*c->c_handler)(argc-1, argv+1); + if (connected) { + proxflag = 1; + } + else { + proxflag = 0; + } + pswitch(0); + (void) signal(SIGINT, oldintr); +} + +void +setcase(argc, argv) + int argc; + char *argv[]; +{ + + mcase = !mcase; + printf("Case mapping %s.\n", onoff(mcase)); + code = mcase; +} + +void +setcr(argc, argv) + int argc; + char *argv[]; +{ + + crflag = !crflag; + printf("Carriage Return stripping %s.\n", onoff(crflag)); + code = crflag; +} + +void +setntrans(argc,argv) + int argc; + char *argv[]; +{ + if (argc == 1) { + ntflag = 0; + printf("Ntrans off.\n"); + code = ntflag; + return; + } + ntflag++; + code = ntflag; + (void) strncpy(ntin, argv[1], 16); + ntin[16] = '\0'; + if (argc == 2) { + ntout[0] = '\0'; + return; + } + (void) strncpy(ntout, argv[2], 16); + ntout[16] = '\0'; +} + +char * +dotrans(name) + char *name; +{ + static char new[MAXPATHLEN]; + char *cp1, *cp2 = new; + int i, ostop, found; + + for (ostop = 0; *(ntout + ostop) && ostop < 16; ostop++) + continue; + for (cp1 = name; *cp1; cp1++) { + found = 0; + for (i = 0; *(ntin + i) && i < 16; i++) { + if (*cp1 == *(ntin + i)) { + found++; + if (i < ostop) { + *cp2++ = *(ntout + i); + } + break; + } + } + if (!found) { + *cp2++ = *cp1; + } + } + *cp2 = '\0'; + return (new); +} + +void +setnmap(argc, argv) + int argc; + char *argv[]; +{ + char *cp; + + if (argc == 1) { + mapflag = 0; + printf("Nmap off.\n"); + code = mapflag; + return; + } + if (argc < 3 && !another(&argc, &argv, "mapout")) { + printf("Usage: %s [mapin mapout]\n",argv[0]); + code = -1; + return; + } + mapflag = 1; + code = 1; + cp = strchr(altarg, ' '); + if (proxy) { + while(*++cp == ' ') + continue; + altarg = cp; + cp = strchr(altarg, ' '); + } + *cp = '\0'; + (void) strncpy(mapin, altarg, MAXPATHLEN - 1); + while (*++cp == ' ') + continue; + (void) strncpy(mapout, cp, MAXPATHLEN - 1); +} + +char * +domap(name) + char *name; +{ + static char new[MAXPATHLEN]; + char *cp1 = name, *cp2 = mapin; + char *tp[9], *te[9]; + int i, toks[9], toknum = 0, match = 1; + + for (i=0; i < 9; ++i) { + toks[i] = 0; + } + while (match && *cp1 && *cp2) { + switch (*cp2) { + case '\\': + if (*++cp2 != *cp1) { + match = 0; + } + break; + case '$': + if (*(cp2+1) >= '1' && (*cp2+1) <= '9') { + if (*cp1 != *(++cp2+1)) { + toks[toknum = *cp2 - '1']++; + tp[toknum] = cp1; + while (*++cp1 && *(cp2+1) + != *cp1); + te[toknum] = cp1; + } + cp2++; + break; + } + /* FALLTHROUGH */ + default: + if (*cp2 != *cp1) { + match = 0; + } + break; + } + if (match && *cp1) { + cp1++; + } + if (match && *cp2) { + cp2++; + } + } + if (!match && *cp1) /* last token mismatch */ + { + toks[toknum] = 0; + } + cp1 = new; + *cp1 = '\0'; + cp2 = mapout; + while (*cp2) { + match = 0; + switch (*cp2) { + case '\\': + if (*(cp2 + 1)) { + *cp1++ = *++cp2; + } + break; + case '[': +LOOP: + if (*++cp2 == '$' && isdigit(*(cp2+1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + match = 1; + } + else if (toks[toknum = *cp2 - '1']) { + char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp1++ = *cp3++; + } + match = 1; + } + } + else { + while (*cp2 && *cp2 != ',' && + *cp2 != ']') { + if (*cp2 == '\\') { + cp2++; + } + else if (*cp2 == '$' && + isdigit(*(cp2+1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + } + else if (toks[toknum = + *cp2 - '1']) { + char *cp3=tp[toknum]; + + while (cp3 != + te[toknum]) { + *cp1++ = *cp3++; + } + } + } + else if (*cp2) { + *cp1++ = *cp2++; + } + } + if (!*cp2) { + printf("nmap: unbalanced brackets\n"); + return (name); + } + match = 1; + cp2--; + } + if (match) { + while (*++cp2 && *cp2 != ']') { + if (*cp2 == '\\' && *(cp2 + 1)) { + cp2++; + } + } + if (!*cp2) { + printf("nmap: unbalanced brackets\n"); + return (name); + } + break; + } + switch (*++cp2) { + case ',': + goto LOOP; + case ']': + break; + default: + cp2--; + goto LOOP; + } + break; + case '$': + if (isdigit(*(cp2 + 1))) { + if (*++cp2 == '0') { + char *cp3 = name; + + while (*cp3) { + *cp1++ = *cp3++; + } + } + else if (toks[toknum = *cp2 - '1']) { + char *cp3 = tp[toknum]; + + while (cp3 != te[toknum]) { + *cp1++ = *cp3++; + } + } + break; + } + /* intentional drop through */ + default: + *cp1++ = *cp2; + break; + } + cp2++; + } + *cp1 = '\0'; + if (!*new) { + return (name); + } + return (new); +} + +void +setpassive(argc, argv) + int argc; + char *argv[]; +{ + + passivemode = !passivemode; + printf("Passive mode %s.\n", onoff(passivemode)); + code = passivemode; +} + +void +setsunique(argc, argv) + int argc; + char *argv[]; +{ + + sunique = !sunique; + printf("Store unique %s.\n", onoff(sunique)); + code = sunique; +} + +void +setrunique(argc, argv) + int argc; + char *argv[]; +{ + + runique = !runique; + printf("Receive unique %s.\n", onoff(runique)); + code = runique; +} + +/* change directory to perent directory */ +void +cdup(argc, argv) + int argc; + char *argv[]; +{ + + if (command("CDUP") == ERROR && code == 500) { + if (verbose) + printf("CDUP command not recognized, trying XCUP\n"); + (void) command("XCUP"); + } +} + +/* restart transfer at specific point */ +void +restart(argc, argv) + int argc; + char *argv[]; +{ + + if (argc != 2) + printf("restart: offset not specified\n"); + else { + restart_point = atol(argv[1]); + printf("restarting at %qd. %s\n", restart_point, + "execute get, put or append to initiate transfer"); + } +} + +/* show remote system type */ +void +syst(argc, argv) + int argc; + char *argv[]; +{ + + (void) command("SYST"); +} + +void +macdef(argc, argv) + int argc; + char *argv[]; +{ + char *tmp; + int c; + + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + code = -1; + return; + } + if (argc < 2 && !another(&argc, &argv, "macro name")) { + printf("Usage: %s macro_name\n",argv[0]); + code = -1; + return; + } + if (interactive) { + printf("Enter macro line by line, terminating it with a null line\n"); + } + (void) strncpy(macros[macnum].mac_name, argv[1], 8); + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum - 1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf+4096) { + if ((c = getchar()) == EOF) { + printf("macdef:end of file encountered\n"); + code = -1; + return; + } + if ((*tmp = c) == '\n') { + if (tmp == macros[macnum].mac_start) { + macros[macnum++].mac_end = tmp; + code = 0; + return; + } + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + code = 0; + return; + } + *tmp = '\0'; + } + tmp++; + } + while (1) { + while ((c = getchar()) != '\n' && c != EOF) + /* LOOP */; + if (c == EOF || getchar() == '\n') { + printf("Macro not defined - 4k buffer exceeded\n"); + code = -1; + return; + } + } +} + +/* + * get size of file on remote machine + */ +void +sizecmd(argc, argv) + int argc; + char *argv[]; +{ + + if (argc < 2 && !another(&argc, &argv, "filename")) { + printf("usage: %s filename\n", argv[0]); + code = -1; + return; + } + (void) command("SIZE %s", argv[1]); +} + +/* + * get last modification time of file on remote machine + */ +void +modtime(argc, argv) + int argc; + char *argv[]; +{ + int overbose; + + if (argc < 2 && !another(&argc, &argv, "filename")) { + printf("usage: %s filename\n", argv[0]); + code = -1; + return; + } + overbose = verbose; + if (debug == 0) + verbose = -1; + if (command("MDTM %s", argv[1]) == COMPLETE) { + int yy, mo, day, hour, min, sec; + sscanf(reply_string, "%*s %04d%02d%02d%02d%02d%02d", &yy, &mo, + &day, &hour, &min, &sec); + /* might want to print this in local time */ + printf("%s\t%02d/%02d/%04d %02d:%02d:%02d GMT\n", argv[1], + mo, day, yy, hour, min, sec); + } else + printf("%s\n", reply_string); + verbose = overbose; +} + +/* + * show status on reomte machine + */ +void +rmtstatus(argc, argv) + int argc; + char *argv[]; +{ + + (void) command(argc > 1 ? "STAT %s" : "STAT" , argv[1]); +} + +/* + * get file if modtime is more recent than current file + */ +void +newer(argc, argv) + int argc; + char *argv[]; +{ + + if (getit(argc, argv, -1, "w")) + printf("Local file \"%s\" is newer than remote file \"%s\"\n", + argv[2], argv[1]); +} diff --git a/ftp.tproj/cmdtab.c b/ftp.tproj/cmdtab.c new file mode 100644 index 0000000..177dd59 --- /dev/null +++ b/ftp.tproj/cmdtab.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include "ftp_var.h" + +/* + * User FTP -- Command Tables. + */ + +char accounthelp[] = "send account command to remote server"; +char appendhelp[] = "append to a file"; +char asciihelp[] = "set ascii transfer type"; +char beephelp[] = "beep when command completed"; +char binaryhelp[] = "set binary transfer type"; +char casehelp[] = "toggle mget upper/lower case id mapping"; +char cdhelp[] = "change remote working directory"; +char cduphelp[] = "change remote working directory to parent directory"; +char chmodhelp[] = "change file permissions of remote file"; +char connecthelp[] = "connect to remote tftp"; +char crhelp[] = "toggle carriage return stripping on ascii gets"; +char deletehelp[] = "delete remote file"; +char debughelp[] = "toggle/set debugging mode"; +char dirhelp[] = "list contents of remote directory"; +char disconhelp[] = "terminate ftp session"; +char domachelp[] = "execute macro"; +char formhelp[] = "set file transfer format"; +char globhelp[] = "toggle metacharacter expansion of local file names"; +char hashhelp[] = "toggle printing `#' for each buffer transferred"; +char helphelp[] = "print local help information"; +char idlehelp[] = "get (set) idle timer on remote side"; +char lcdhelp[] = "change local working directory"; +char lshelp[] = "list contents of remote directory"; +char macdefhelp[] = "define a macro"; +char mdeletehelp[] = "delete multiple files"; +char mdirhelp[] = "list contents of multiple remote directories"; +char mgethelp[] = "get multiple files"; +char mkdirhelp[] = "make directory on the remote machine"; +char mlshelp[] = "list contents of multiple remote directories"; +char modtimehelp[] = "show last modification time of remote file"; +char modehelp[] = "set file transfer mode"; +char mputhelp[] = "send multiple files"; +char newerhelp[] = "get file if remote file is newer than local file "; +char nlisthelp[] = "nlist contents of remote directory"; +char nmaphelp[] = "set templates for default file name mapping"; +char ntranshelp[] = "set translation table for default file name mapping"; +char porthelp[] = "toggle use of PORT cmd for each data connection"; +char prompthelp[] = "force interactive prompting on multiple commands"; +char proxyhelp[] = "issue command on alternate connection"; +char pwdhelp[] = "print working directory on remote machine"; +char quithelp[] = "terminate ftp session and exit"; +char quotehelp[] = "send arbitrary ftp command"; +char receivehelp[] = "receive file"; +char regethelp[] = "get file restarting at end of local file"; +char remotehelp[] = "get help from remote server"; +char renamehelp[] = "rename file"; +char restarthelp[]= "restart file transfer at bytecount"; +char rmdirhelp[] = "remove directory on the remote machine"; +char rmtstatushelp[]="show status of remote machine"; +char runiquehelp[] = "toggle store unique for local files"; +char resethelp[] = "clear queued command replies"; +char sendhelp[] = "send one file"; +char passivehelp[] = "enter passive transfer mode"; +char sitehelp[] = "send site specific command to remote server\n\t\tTry \"rhelp site\" or \"site help\" for more information"; +char shellhelp[] = "escape to the shell"; +char sizecmdhelp[] = "show size of remote file"; +char statushelp[] = "show current status"; +char structhelp[] = "set file transfer structure"; +char suniquehelp[] = "toggle store unique on remote machine"; +char systemhelp[] = "show remote system type"; +char tenexhelp[] = "set tenex file transfer type"; +char tracehelp[] = "toggle packet tracing"; +char typehelp[] = "set file transfer type"; +char umaskhelp[] = "get (set) umask on remote side"; +char userhelp[] = "send new user information"; +char verbosehelp[] = "toggle verbose mode"; + +struct cmd cmdtab[] = { + { "!", shellhelp, 0, 0, 0, shell }, + { "$", domachelp, 1, 0, 0, domacro }, + { "account", accounthelp, 0, 1, 1, account}, + { "append", appendhelp, 1, 1, 1, put }, + { "ascii", asciihelp, 0, 1, 1, setascii }, + { "bell", beephelp, 0, 0, 0, setbell }, + { "binary", binaryhelp, 0, 1, 1, setbinary }, + { "bye", quithelp, 0, 0, 0, quit }, + { "case", casehelp, 0, 0, 1, setcase }, + { "cd", cdhelp, 0, 1, 1, cd }, + { "cdup", cduphelp, 0, 1, 1, cdup }, + { "chmod", chmodhelp, 0, 1, 1, do_chmod }, + { "close", disconhelp, 0, 1, 1, disconnect }, + { "cr", crhelp, 0, 0, 0, setcr }, + { "delete", deletehelp, 0, 1, 1, delete }, + { "debug", debughelp, 0, 0, 0, setdebug }, + { "dir", dirhelp, 1, 1, 1, ls }, + { "disconnect", disconhelp, 0, 1, 1, disconnect }, + { "form", formhelp, 0, 1, 1, setform }, + { "get", receivehelp, 1, 1, 1, get }, + { "glob", globhelp, 0, 0, 0, setglob }, + { "hash", hashhelp, 0, 0, 0, sethash }, + { "help", helphelp, 0, 0, 1, help }, + { "idle", idlehelp, 0, 1, 1, idle }, + { "image", binaryhelp, 0, 1, 1, setbinary }, + { "lcd", lcdhelp, 0, 0, 0, lcd }, + { "ls", lshelp, 1, 1, 1, ls }, + { "macdef", macdefhelp, 0, 0, 0, macdef }, + { "mdelete", mdeletehelp, 1, 1, 1, mdelete }, + { "mdir", mdirhelp, 1, 1, 1, mls }, + { "mget", mgethelp, 1, 1, 1, mget }, + { "mkdir", mkdirhelp, 0, 1, 1, makedir }, + { "mls", mlshelp, 1, 1, 1, mls }, + { "mode", modehelp, 0, 1, 1, setftmode }, + { "modtime", modtimehelp, 0, 1, 1, modtime }, + { "mput", mputhelp, 1, 1, 1, mput }, + { "newer", newerhelp, 1, 1, 1, newer }, + { "nmap", nmaphelp, 0, 0, 1, setnmap }, + { "nlist", nlisthelp, 1, 1, 1, ls }, + { "ntrans", ntranshelp, 0, 0, 1, setntrans }, + { "open", connecthelp, 0, 0, 1, setpeer }, + { "passive", passivehelp, 0, 0, 0, setpassive }, + { "prompt", prompthelp, 0, 0, 0, setprompt }, + { "proxy", proxyhelp, 0, 0, 1, doproxy }, + { "sendport", porthelp, 0, 0, 0, setport }, + { "put", sendhelp, 1, 1, 1, put }, + { "pwd", pwdhelp, 0, 1, 1, pwd }, + { "quit", quithelp, 0, 0, 0, quit }, + { "quote", quotehelp, 1, 1, 1, quote }, + { "recv", receivehelp, 1, 1, 1, get }, + { "reget", regethelp, 1, 1, 1, reget }, + { "rstatus", rmtstatushelp, 0, 1, 1, rmtstatus }, + { "rhelp", remotehelp, 0, 1, 1, rmthelp }, + { "rename", renamehelp, 0, 1, 1, renamefile }, + { "reset", resethelp, 0, 1, 1, reset }, + { "restart", restarthelp, 1, 1, 1, restart }, + { "rmdir", rmdirhelp, 0, 1, 1, removedir }, + { "runique", runiquehelp, 0, 0, 1, setrunique }, + { "send", sendhelp, 1, 1, 1, put }, + { "site", sitehelp, 0, 1, 1, site }, + { "size", sizecmdhelp, 1, 1, 1, sizecmd }, + { "status", statushelp, 0, 0, 1, status }, + { "struct", structhelp, 0, 1, 1, setstruct }, + { "system", systemhelp, 0, 1, 1, syst }, + { "sunique", suniquehelp, 0, 0, 1, setsunique }, + { "tenex", tenexhelp, 0, 1, 1, settenex }, + { "trace", tracehelp, 0, 0, 0, settrace }, + { "type", typehelp, 0, 1, 1, settype }, + { "user", userhelp, 0, 1, 1, user }, + { "umask", umaskhelp, 0, 1, 1, do_umask }, + { "verbose", verbosehelp, 0, 0, 0, setverbose }, + { "?", helphelp, 0, 0, 1, help }, + { 0 }, +}; + +int NCMDS = (sizeof (cmdtab) / sizeof (cmdtab[0])) - 1; diff --git a/ftp.tproj/domacro.c b/ftp.tproj/domacro.c new file mode 100644 index 0000000..19f0539 --- /dev/null +++ b/ftp.tproj/domacro.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include "ftp_var.h" + +void +domacro(argc, argv) + int argc; + char *argv[]; +{ + int i, j, count = 2, loopflg = 0; + char *cp1, *cp2, line2[200]; + struct cmd *c; + + if (argc < 2 && !another(&argc, &argv, "macro name")) { + printf("Usage: %s macro_name.\n", argv[0]); + code = -1; + return; + } + for (i = 0; i < macnum; ++i) { + if (!strncmp(argv[1], macros[i].mac_name, 9)) { + break; + } + } + if (i == macnum) { + printf("'%s' macro not found.\n", argv[1]); + code = -1; + return; + } + (void) strcpy(line2, line); +TOP: + cp1 = macros[i].mac_start; + while (cp1 != macros[i].mac_end) { + while (isspace(*cp1)) { + cp1++; + } + cp2 = line; + while (*cp1 != '\0') { + switch(*cp1) { + case '\\': + *cp2++ = *++cp1; + break; + case '$': + if (isdigit(*(cp1+1))) { + j = 0; + while (isdigit(*++cp1)) { + j = 10*j + *cp1 - '0'; + } + cp1--; + if (argc - 2 >= j) { + (void) strcpy(cp2, argv[j+1]); + cp2 += strlen(argv[j+1]); + } + break; + } + if (*(cp1+1) == 'i') { + loopflg = 1; + cp1++; + if (count < argc) { + (void) strcpy(cp2, argv[count]); + cp2 += strlen(argv[count]); + } + break; + } + /* intentional drop through */ + default: + *cp2++ = *cp1; + break; + } + if (*cp1 != '\0') { + cp1++; + } + } + *cp2 = '\0'; + makeargv(); + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + code = -1; + } + else if (c == 0) { + printf("?Invalid command\n"); + code = -1; + } + else if (c->c_conn && !connected) { + printf("Not connected.\n"); + code = -1; + } + else { + if (verbose) { + printf("%s\n",line); + } + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) { + (void) putchar('\007'); + } + (void) strcpy(line, line2); + makeargv(); + argc = margc; + argv = margv; + } + if (cp1 != macros[i].mac_end) { + cp1++; + } + } + if (loopflg && ++count < argc) { + goto TOP; + } +} diff --git a/ftp.tproj/extern.h b/ftp.tproj/extern.h new file mode 100644 index 0000000..e23f324 --- /dev/null +++ b/ftp.tproj/extern.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1994 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.3 (Berkeley) 10/9/94 + */ + +struct timeval; +struct fd_set; + +void abort_remote __P((FILE *)); +void abortpt __P(()); +void abortrecv __P(()); +void abortsend __P(()); +void account __P((int, char **)); +int another __P((int *, char ***, char *)); +void blkfree __P((char **)); +void cd __P((int, char **)); +void cdup __P((int, char **)); +void changetype __P((int, int)); +void cmdabort __P(()); +void cmdscanner __P((int)); +int command __P((const char *, ...)); +int confirm __P((char *, char *)); +FILE *dataconn __P((char *)); +void delete __P((int, char **)); +void disconnect __P((int, char **)); +void do_chmod __P((int, char **)); +void do_umask __P((int, char **)); +void domacro __P((int, char **)); +char *domap __P((char *)); +void doproxy __P((int, char **)); +char *dotrans __P((char *)); +int empty __P((struct fd_set *, int)); +void fatal __P((char *)); +void get __P((int, char **)); +struct cmd *getcmd __P((char *)); +int getit __P((int, char **, int, char *)); +int getreply __P((int)); +int globulize __P((char **)); +char *gunique __P((char *)); +void help __P((int, char **)); +char *hookup __P((char *, int)); +void idle __P((int, char **)); +int initconn __P((void)); +void intr __P(()); +void lcd __P((int, char **)); +int login __P((char *)); +void lostpeer __P(()); +void ls __P((int, char **)); +void mabort __P((int)); +void macdef __P((int, char **)); +void makeargv __P((void)); +void makedir __P((int, char **)); +void mdelete __P((int, char **)); +void mget __P((int, char **)); +void mls __P((int, char **)); +void modtime __P((int, char **)); +void mput __P((int, char **)); +char *onoff __P((int)); +void newer __P((int, char **)); +void proxabort __P(()); +void proxtrans __P((char *, char *, char *)); +void psabort __P(()); +void pswitch __P((int)); +void ptransfer __P((char *, long, struct timeval *, struct timeval *)); +void put __P((int, char **)); +void pwd __P((int, char **)); +void quit __P((int, char **)); +void quote __P((int, char **)); +void quote1 __P((char *, int, char **)); +void recvrequest __P((char *, char *, char *, char *, int)); +void reget __P((int, char **)); +char *remglob __P((char **, int)); +void removedir __P((int, char **)); +void renamefile __P((int, char **)); +void reset __P((int, char **)); +void restart __P((int, char **)); +void rmthelp __P((int, char **)); +void rmtstatus __P((int, char **)); +int ruserpass __P((char *, char **, char **, char **)); +void sendrequest __P((char *, char *, char *, int)); +void setascii __P((int, char **)); +void setbell __P((int, char **)); +void setbinary __P((int, char **)); +void setcase __P((int, char **)); +void setcr __P((int, char **)); +void setdebug __P((int, char **)); +void setform __P((int, char **)); +void setftmode __P((int, char **)); +void setglob __P((int, char **)); +void sethash __P((int, char **)); +void setnmap __P((int, char **)); +void setntrans __P((int, char **)); +void setpassive __P((int, char **)); +void setpeer __P((int, char **)); +void setport __P((int, char **)); +void setprompt __P((int, char **)); +void setrunique __P((int, char **)); +void setstruct __P((int, char **)); +void setsunique __P((int, char **)); +void settenex __P((int, char **)); +void settrace __P((int, char **)); +void settype __P((int, char **)); +void setverbose __P((int, char **)); +void shell __P((int, char **)); +void site __P((int, char **)); +void sizecmd __P((int, char **)); +char *slurpstring __P((void)); +void status __P((int, char **)); +void syst __P((int, char **)); +void tvsub __P((struct timeval *, struct timeval *, struct timeval *)); +void user __P((int, char **)); + +extern jmp_buf abortprox; +extern int abrtflag; +extern struct cmd cmdtab[]; +extern FILE *cout; +extern int data; +extern char *home; +extern jmp_buf jabort; +extern int proxy; +extern char reply_string[]; +extern off_t restart_point; +extern int NCMDS; diff --git a/ftp.tproj/ftp.1 b/ftp.tproj/ftp.1 new file mode 100644 index 0000000..79dcbae --- /dev/null +++ b/ftp.tproj/ftp.1 @@ -0,0 +1,1157 @@ +.\" Copyright (c) 1985, 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ftp.1 8.3 (Berkeley) 10/9/94 +.\" +.Dd October 9, 1994 +.Dt FTP 1 +.Os BSD 4.2 +.Sh NAME +.Nm ftp +.Nd +.Tn ARPANET +file transfer program +.Sh SYNOPSIS +.Nm ftp +.Op Fl v +.Op Fl d +.Op Fl i +.Op Fl n +.Op Fl g +.Op Ar host +.Sh DESCRIPTION +.Nm Ftp +is the user interface to the +.Tn ARPANET +standard File Transfer Protocol. +The program allows a user to transfer files to and from a +remote network site. +.Pp +Options may be specified at the command line, or to the +command interpreter. +.Bl -tag -width flag +.It Fl v +Verbose option forces +.Nm ftp +to show all responses from the remote server, as well +as report on data transfer statistics. +.It Fl n +Restrains +.Nm ftp +from attempting \*(Lqauto-login\*(Rq upon initial connection. +If auto-login is enabled, +.Nm ftp +will check the +.Pa .netrc +(see below) file in the user's home directory for an entry describing +an account on the remote machine. +If no entry exists, +.Nm ftp +will prompt for the remote machine login name (default is the user +identity on the local machine), and, if necessary, prompt for a password +and an account with which to login. +.It Fl i +Turns off interactive prompting during +multiple file transfers. +.It Fl d +Enables debugging. +.It Fl g +Disables file name globbing. +.El +.Pp +The client host with which +.Nm ftp +is to communicate may be specified on the command line. +If this is done, +.Nm ftp +will immediately attempt to establish a connection to an +.Tn FTP +server on that host; otherwise, +.Nm ftp +will enter its command interpreter and await instructions +from the user. +When +.Nm ftp +is awaiting commands from the user the prompt +.Ql ftp> +is provided to the user. +The following commands are recognized +by +.Nm ftp : +.Bl -tag -width Fl +.It Ic \&! Op Ar command Op Ar args +Invoke an interactive shell on the local machine. +If there are arguments, the first is taken to be a command to execute +directly, with the rest of the arguments as its arguments. +.It Ic \&$ Ar macro-name Op Ar args +Execute the macro +.Ar macro-name +that was defined with the +.Ic macdef +command. +Arguments are passed to the macro unglobbed. +.It Ic account Op Ar passwd +Supply a supplemental password required by a remote system for access +to resources once a login has been successfully completed. +If no argument is included, the user will be prompted for an account +password in a non-echoing input mode. +.It Ic append Ar local-file Op Ar remote-file +Append a local file to a file on the remote machine. +If +.Ar remote-file +is left unspecified, the local file name is used in naming the +remote file after being altered by any +.Ic ntrans +or +.Ic nmap +setting. +File transfer uses the current settings for +.Ic type , +.Ic format , +.Ic mode , +and +.Ic structure . +.It Ic ascii +Set the file transfer +.Ic type +to network +.Tn ASCII . +This is the default type. +.It Ic bell +Arrange that a bell be sounded after each file transfer +command is completed. +.It Ic binary +Set the file transfer +.Ic type +to support binary image transfer. +.It Ic bye +Terminate the +.Tn FTP +session with the remote server +and exit +.Nm ftp . +An end of file will also terminate the session and exit. +.It Ic case +Toggle remote computer file name case mapping during +.Ic mget +commands. +When +.Ic case +is on (default is off), remote computer file names with all letters in +upper case are written in the local directory with the letters mapped +to lower case. +.It Ic \&cd Ar remote-directory +Change the working directory on the remote machine +to +.Ar remote-directory . +.It Ic cdup +Change the remote machine working directory to the parent of the +current remote machine working directory. +.It Ic chmod Ar mode file-name +Change the permission modes of the file +.Ar file-name +on the remote +sytem to +.Ar mode . +.It Ic close +Terminate the +.Tn FTP +session with the remote server, and +return to the command interpreter. +Any defined macros are erased. +.It Ic \&cr +Toggle carriage return stripping during +ascii type file retrieval. +Records are denoted by a carriage return/linefeed sequence +during ascii type file transfer. +When +.Ic \&cr +is on (the default), carriage returns are stripped from this +sequence to conform with the +.Ux +single linefeed record +delimiter. +Records on +.Pf non\- Ns Ux +remote systems may contain single linefeeds; +when an ascii type transfer is made, these linefeeds may be +distinguished from a record delimiter only when +.Ic \&cr +is off. +.It Ic delete Ar remote-file +Delete the file +.Ar remote-file +on the remote machine. +.It Ic debug Op Ar debug-value +Toggle debugging mode. +If an optional +.Ar debug-value +is specified it is used to set the debugging level. +When debugging is on, +.Nm ftp +prints each command sent to the remote machine, preceded +by the string +.Ql \-\-> +.It Xo +.Ic dir +.Op Ar remote-directory +.Op Ar local-file +.Xc +Print a listing of the directory contents in the +directory, +.Ar remote-directory , +and, optionally, placing the output in +.Ar local-file . +If interactive prompting is on, +.Nm ftp +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic dir +output. +If no directory is specified, the current working +directory on the remote machine is used. +If no local +file is specified, or +.Ar local-file +is +.Fl , +output comes to the terminal. +.It Ic disconnect +A synonym for +.Ar close . +.It Ic form Ar format +Set the file transfer +.Ic form +to +.Ar format . +The default format is \*(Lqfile\*(Rq. +.It Ic get Ar remote-file Op Ar local-file +Retrieve the +.Ar remote-file +and store it on the local machine. +If the local +file name is not specified, it is given the same +name it has on the remote machine, subject to +alteration by the current +.Ic case , +.Ic ntrans , +and +.Ic nmap +settings. +The current settings for +.Ic type , +.Ic form , +.Ic mode , +and +.Ic structure +are used while transferring the file. +.It Ic glob +Toggle filename expansion for +.Ic mdelete , +.Ic mget +and +.Ic mput . +If globbing is turned off with +.Ic glob , +the file name arguments +are taken literally and not expanded. +Globbing for +.Ic mput +is done as in +.Xr csh 1 . +For +.Ic mdelete +and +.Ic mget , +each remote file name is expanded +separately on the remote machine and the lists are not merged. +Expansion of a directory name is likely to be +different from expansion of the name of an ordinary file: +the exact result depends on the foreign operating system and ftp server, +and can be previewed by doing +.Ql mls remote-files \- +Note: +.Ic mget +and +.Ic mput +are not meant to transfer +entire directory subtrees of files. +That can be done by +transferring a +.Xr tar 1 +archive of the subtree (in binary mode). +.It Ic hash +Toggle hash-sign (``#'') printing for each data block +transferred. +The size of a data block is 1024 bytes. +.It Ic help Op Ar command +Print an informative message about the meaning of +.Ar command . +If no argument is given, +.Nm ftp +prints a list of the known commands. +.It Ic idle Op Ar seconds +Set the inactivity timer on the remote server to +.Ar seconds +seconds. +If +.Ar seconds +is omitted, the current inactivity timer is printed. +.It Ic lcd Op Ar directory +Change the working directory on the local machine. +If +no +.Ar directory +is specified, the user's home directory is used. +.It Xo +.Ic \&ls +.Op Ar remote-directory +.Op Ar local-file +.Xc +Print a listing of the contents of a +directory on the remote machine. +The listing includes any system-dependent information that the server +chooses to include; for example, most +.Ux +systems will produce +output from the command +.Ql ls \-l . +(See also +.Ic nlist . ) +If +.Ar remote-directory +is left unspecified, the current working directory is used. +If interactive prompting is on, +.Nm ftp +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic \&ls +output. +If no local file is specified, or if +.Ar local-file +is +.Sq Fl , +the output is sent to the terminal. +.It Ic macdef Ar macro-name +Define a macro. +Subsequent lines are stored as the macro +.Ar macro-name ; +a null line (consecutive newline characters +in a file or +carriage returns from the terminal) terminates macro input mode. +There is a limit of 16 macros and 4096 total characters in all +defined macros. +Macros remain defined until a +.Ic close +command is executed. +The macro processor interprets `$' and `\e' as special characters. +A `$' followed by a number (or numbers) is replaced by the +corresponding argument on the macro invocation command line. +A `$' followed by an `i' signals that macro processor that the +executing macro is to be looped. +On the first pass `$i' is +replaced by the first argument on the macro invocation command line, +on the second pass it is replaced by the second argument, and so on. +A `\e' followed by any character is replaced by that character. +Use the `\e' to prevent special treatment of the `$'. +.It Ic mdelete Op Ar remote-files +Delete the +.Ar remote-files +on the remote machine. +.It Ic mdir Ar remote-files local-file +Like +.Ic dir , +except multiple remote files may be specified. +If interactive prompting is on, +.Nm ftp +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic mdir +output. +.It Ic mget Ar remote-files +Expand the +.Ar remote-files +on the remote machine +and do a +.Ic get +for each file name thus produced. +See +.Ic glob +for details on the filename expansion. +Resulting file names will then be processed according to +.Ic case , +.Ic ntrans , +and +.Ic nmap +settings. +Files are transferred into the local working directory, +which can be changed with +.Ql lcd directory ; +new local directories can be created with +.Ql "\&! mkdir directory" . +.It Ic mkdir Ar directory-name +Make a directory on the remote machine. +.It Ic mls Ar remote-files local-file +Like +.Ic nlist , +except multiple remote files may be specified, +and the +.Ar local-file +must be specified. +If interactive prompting is on, +.Nm ftp +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic mls +output. +.It Ic mode Op Ar mode-name +Set the file transfer +.Ic mode +to +.Ar mode-name . +The default mode is \*(Lqstream\*(Rq mode. +.It Ic modtime Ar file-name +Show the last modification time of the file on the remote machine. +.It Ic mput Ar local-files +Expand wild cards in the list of local files given as arguments +and do a +.Ic put +for each file in the resulting list. +See +.Ic glob +for details of filename expansion. +Resulting file names will then be processed according to +.Ic ntrans +and +.Ic nmap +settings. +.It Ic newer Ar file-name +Get the file only if the modification time of the remote file is more +recent that the file on the current system. +If the file does not +exist on the current system, the remote file is considered +.Ic newer . +Otherwise, this command is identical to +.Ar get . +.It Xo +.Ic nlist +.Op Ar remote-directory +.Op Ar local-file +.Xc +Print a list of the files in a +directory on the remote machine. +If +.Ar remote-directory +is left unspecified, the current working directory is used. +If interactive prompting is on, +.Nm ftp +will prompt the user to verify that the last argument is indeed the +target local file for receiving +.Ic nlist +output. +If no local file is specified, or if +.Ar local-file +is +.Fl , +the output is sent to the terminal. +.It Ic nmap Op Ar inpattern outpattern +Set or unset the filename mapping mechanism. +If no arguments are specified, the filename mapping mechanism is unset. +If arguments are specified, remote filenames are mapped during +.Ic mput +commands and +.Ic put +commands issued without a specified remote target filename. +If arguments are specified, local filenames are mapped during +.Ic mget +commands and +.Ic get +commands issued without a specified local target filename. +This command is useful when connecting to a +.No non\- Ns Ux +remote computer +with different file naming conventions or practices. +The mapping follows the pattern set by +.Ar inpattern +and +.Ar outpattern . +.Op Ar Inpattern +is a template for incoming filenames (which may have already been +processed according to the +.Ic ntrans +and +.Ic case +settings). +Variable templating is accomplished by including the +sequences `$1', `$2', ..., `$9' in +.Ar inpattern . +Use `\\' to prevent this special treatment of the `$' character. +All other characters are treated literally, and are used to determine the +.Ic nmap +.Op Ar inpattern +variable values. +For example, given +.Ar inpattern +$1.$2 and the remote file name "mydata.data", $1 would have the value +"mydata", and $2 would have the value "data". +The +.Ar outpattern +determines the resulting mapped filename. +The sequences `$1', `$2', ...., `$9' are replaced by any value resulting +from the +.Ar inpattern +template. +The sequence `$0' is replace by the original filename. +Additionally, the sequence +.Ql Op Ar seq1 , Ar seq2 +is replaced by +.Op Ar seq1 +if +.Ar seq1 +is not a null string; otherwise it is replaced by +.Ar seq2 . +For example, the command +.Pp +.Bd -literal -offset indent -compact +nmap $1.$2.$3 [$1,$2].[$2,file] +.Ed +.Pp +would yield +the output filename "myfile.data" for input filenames "myfile.data" and +"myfile.data.old", "myfile.file" for the input filename "myfile", and +"myfile.myfile" for the input filename ".myfile". +Spaces may be included in +.Ar outpattern , +as in the example: `nmap $1 sed "s/ *$//" > $1' . +Use the `\e' character to prevent special treatment +of the `$','[','[', and `,' characters. +.It Ic ntrans Op Ar inchars Op Ar outchars +Set or unset the filename character translation mechanism. +If no arguments are specified, the filename character +translation mechanism is unset. +If arguments are specified, characters in +remote filenames are translated during +.Ic mput +commands and +.Ic put +commands issued without a specified remote target filename. +If arguments are specified, characters in +local filenames are translated during +.Ic mget +commands and +.Ic get +commands issued without a specified local target filename. +This command is useful when connecting to a +.No non\- Ns Ux +remote computer +with different file naming conventions or practices. +Characters in a filename matching a character in +.Ar inchars +are replaced with the corresponding character in +.Ar outchars . +If the character's position in +.Ar inchars +is longer than the length of +.Ar outchars , +the character is deleted from the file name. +.It Ic open Ar host Op Ar port +Establish a connection to the specified +.Ar host +.Tn FTP +server. +An optional port number may be supplied, +in which case, +.Nm ftp +will attempt to contact an +.Tn FTP +server at that port. +If the +.Ic auto-login +option is on (default), +.Nm ftp +will also attempt to automatically log the user in to +the +.Tn FTP +server (see below). +.It Ic passive +Toggle passive mode. If passive mode is turned on +(default is off), the ftp client will +send a +.Dv PASV +command for all data connections instead of the usual +.Dv PORT +command. The +.Dv PASV +command requests that the remote server open a port for the data connection +and return the address of that port. The remote server listens on that +port and the client connects to it. When using the more traditional +.Dv PORT +command, the client listens on a port and sends that address to the remote +server, who connects back to it. Passive mode is useful when using +.Nm ftp +through a gateway router or host that controls the directionality of +traffic. +(Note that though ftp servers are required to support the +.Dv PASV +command by RFC 1123, some do not.) +.It Ic prompt +Toggle interactive prompting. +Interactive prompting +occurs during multiple file transfers to allow the +user to selectively retrieve or store files. +If prompting is turned off (default is on), any +.Ic mget +or +.Ic mput +will transfer all files, and any +.Ic mdelete +will delete all files. +.It Ic proxy Ar ftp-command +Execute an ftp command on a secondary control connection. +This command allows simultaneous connection to two remote ftp +servers for transferring files between the two servers. +The first +.Ic proxy +command should be an +.Ic open , +to establish the secondary control connection. +Enter the command "proxy ?" to see other ftp commands executable on the +secondary connection. +The following commands behave differently when prefaced by +.Ic proxy : +.Ic open +will not define new macros during the auto-login process, +.Ic close +will not erase existing macro definitions, +.Ic get +and +.Ic mget +transfer files from the host on the primary control connection +to the host on the secondary control connection, and +.Ic put , +.Ic mput , +and +.Ic append +transfer files from the host on the secondary control connection +to the host on the primary control connection. +Third party file transfers depend upon support of the ftp protocol +.Dv PASV +command by the server on the secondary control connection. +.It Ic put Ar local-file Op Ar remote-file +Store a local file on the remote machine. +If +.Ar remote-file +is left unspecified, the local file name is used +after processing according to any +.Ic ntrans +or +.Ic nmap +settings +in naming the remote file. +File transfer uses the +current settings for +.Ic type , +.Ic format , +.Ic mode , +and +.Ic structure . +.It Ic pwd +Print the name of the current working directory on the remote +machine. +.It Ic quit +A synonym for +.Ic bye . +.It Ic quote Ar arg1 arg2 ... +The arguments specified are sent, verbatim, to the remote +.Tn FTP +server. +.It Ic recv Ar remote-file Op Ar local-file +A synonym for get. +.It Ic reget Ar remote-file Op Ar local-file +Reget acts like get, except that if +.Ar local-file +exists and is +smaller than +.Ar remote-file , +.Ar local-file +is presumed to be +a partially transferred copy of +.Ar remote-file +and the transfer +is continued from the apparent point of failure. +This command +is useful when transferring very large files over networks that +are prone to dropping connections. +.It Ic remotehelp Op Ar command-name +Request help from the remote +.Tn FTP +server. +If a +.Ar command-name +is specified it is supplied to the server as well. +.It Ic remotestatus Op Ar file-name +With no arguments, show status of remote machine. +If +.Ar file-name +is specified, show status of +.Ar file-name +on remote machine. +.It Xo +.Ic rename +.Op Ar from +.Op Ar to +.Xc +Rename the file +.Ar from +on the remote machine, to the file +.Ar to . +.It Ic reset +Clear reply queue. +This command re-synchronizes command/reply sequencing with the remote +ftp server. +Resynchronization may be necessary following a violation of the ftp protocol +by the remote server. +.It Ic restart Ar marker +Restart the immediately following +.Ic get +or +.Ic put +at the +indicated +.Ar marker . +On +.Ux +systems, marker is usually a byte +offset into the file. +.It Ic rmdir Ar directory-name +Delete a directory on the remote machine. +.It Ic runique +Toggle storing of files on the local system with unique filenames. +If a file already exists with a name equal to the target +local filename for a +.Ic get +or +.Ic mget +command, a ".1" is appended to the name. +If the resulting name matches another existing file, +a ".2" is appended to the original name. +If this process continues up to ".99", an error +message is printed, and the transfer does not take place. +The generated unique filename will be reported. +Note that +.Ic runique +will not affect local files generated from a shell command +(see below). +The default value is off. +.It Ic send Ar local-file Op Ar remote-file +A synonym for put. +.It Ic sendport +Toggle the use of +.Dv PORT +commands. +By default, +.Nm ftp +will attempt to use a +.Dv PORT +command when establishing +a connection for each data transfer. +The use of +.Dv PORT +commands can prevent delays +when performing multiple file transfers. +If the +.Dv PORT +command fails, +.Nm ftp +will use the default data port. +When the use of +.Dv PORT +commands is disabled, no attempt will be made to use +.Dv PORT +commands for each data transfer. +This is useful +for certain +.Tn FTP +implementations which do ignore +.Dv PORT +commands but, incorrectly, indicate they've been accepted. +.It Ic site Ar arg1 arg2 ... +The arguments specified are sent, verbatim, to the remote +.Tn FTP +server as a +.Dv SITE +command. +.It Ic size Ar file-name +Return size of +.Ar file-name +on remote machine. +.It Ic status +Show the current status of +.Nm ftp . +.It Ic struct Op Ar struct-name +Set the file transfer +.Ar structure +to +.Ar struct-name . +By default \*(Lqstream\*(Rq structure is used. +.It Ic sunique +Toggle storing of files on remote machine under unique file names. +Remote ftp server must support ftp protocol +.Dv STOU +command for +successful completion. +The remote server will report unique name. +Default value is off. +.It Ic system +Show the type of operating system running on the remote machine. +.It Ic tenex +Set the file transfer type to that needed to +talk to +.Tn TENEX +machines. +.It Ic trace +Toggle packet tracing. +.It Ic type Op Ar type-name +Set the file transfer +.Ic type +to +.Ar type-name . +If no type is specified, the current type +is printed. +The default type is network +.Tn ASCII . +.It Ic umask Op Ar newmask +Set the default umask on the remote server to +.Ar newmask . +If +.Ar newmask +is omitted, the current umask is printed. +.It Xo +.Ic user Ar user-name +.Op Ar password +.Op Ar account +.Xc +Identify yourself to the remote +.Tn FTP +server. +If the +.Ar password +is not specified and the server requires it, +.Nm ftp +will prompt the user for it (after disabling local echo). +If an +.Ar account +field is not specified, and the +.Tn FTP +server +requires it, the user will be prompted for it. +If an +.Ar account +field is specified, an account command will +be relayed to the remote server after the login sequence +is completed if the remote server did not require it +for logging in. +Unless +.Nm ftp +is invoked with \*(Lqauto-login\*(Rq disabled, this +process is done automatically on initial connection to +the +.Tn FTP +server. +.It Ic verbose +Toggle verbose mode. +In verbose mode, all responses from +the +.Tn FTP +server are displayed to the user. +In addition, +if verbose is on, when a file transfer completes, statistics +regarding the efficiency of the transfer are reported. +By default, +verbose is on. +.It Ic ? Op Ar command +A synonym for help. +.El +.Pp +Command arguments which have embedded spaces may be quoted with +quote `"' marks. +.Sh ABORTING A FILE TRANSFER +To abort a file transfer, use the terminal interrupt key +(usually Ctrl-C). +Sending transfers will be immediately halted. +Receiving transfers will be halted by sending a ftp protocol +.Dv ABOR +command to the remote server, and discarding any further data received. +The speed at which this is accomplished depends upon the remote +server's support for +.Dv ABOR +processing. +If the remote server does not support the +.Dv ABOR +command, an +.Ql ftp> +prompt will not appear until the remote server has completed +sending the requested file. +.Pp +The terminal interrupt key sequence will be ignored when +.Nm ftp +has completed any local processing and is awaiting a reply +from the remote server. +A long delay in this mode may result from the ABOR processing described +above, or from unexpected behavior by the remote server, including +violations of the ftp protocol. +If the delay results from unexpected remote server behavior, the local +.Nm ftp +program must be killed by hand. +.Sh FILE NAMING CONVENTIONS +Files specified as arguments to +.Nm ftp +commands are processed according to the following rules. +.Bl -enum +.It +If the file name +.Sq Fl +is specified, the +.Ar stdin +(for reading) or +.Ar stdout +(for writing) is used. +.It +If the first character of the file name is +.Sq \&| , +the +remainder of the argument is interpreted as a shell command. +.Nm Ftp +then forks a shell, using +.Xr popen 3 +with the argument supplied, and reads (writes) from the stdout +(stdin). +If the shell command includes spaces, the argument +must be quoted; e.g. +\*(Lq" ls -lt"\*(Rq. +A particularly +useful example of this mechanism is: \*(Lqdir more\*(Rq. +.It +Failing the above checks, if ``globbing'' is enabled, +local file names are expanded +according to the rules used in the +.Xr csh 1 ; +c.f. the +.Ic glob +command. +If the +.Nm ftp +command expects a single local file (.e.g. +.Ic put ) , +only the first filename generated by the "globbing" operation is used. +.It +For +.Ic mget +commands and +.Ic get +commands with unspecified local file names, the local filename is +the remote filename, which may be altered by a +.Ic case , +.Ic ntrans , +or +.Ic nmap +setting. +The resulting filename may then be altered if +.Ic runique +is on. +.It +For +.Ic mput +commands and +.Ic put +commands with unspecified remote file names, the remote filename is +the local filename, which may be altered by a +.Ic ntrans +or +.Ic nmap +setting. +The resulting filename may then be altered by the remote server if +.Ic sunique +is on. +.El +.Sh FILE TRANSFER PARAMETERS +The FTP specification specifies many parameters which may +affect a file transfer. +The +.Ic type +may be one of \*(Lqascii\*(Rq, \*(Lqimage\*(Rq (binary), +\*(Lqebcdic\*(Rq, and \*(Lqlocal byte size\*(Rq (for +.Tn PDP Ns -10's +and +.Tn PDP Ns -20's +mostly). +.Nm Ftp +supports the ascii and image types of file transfer, +plus local byte size 8 for +.Ic tenex +mode transfers. +.Pp +.Nm Ftp +supports only the default values for the remaining +file transfer parameters: +.Ic mode , +.Ic form , +and +.Ic struct . +.Sh THE .netrc FILE +The +.Pa .netrc +file contains login and initialization information +used by the auto-login process. +It resides in the user's home directory. +The following tokens are recognized; they may be separated by spaces, +tabs, or new-lines: +.Bl -tag -width password +.It Ic machine Ar name +Identify a remote machine +.Ar name . +The auto-login process searches the +.Pa .netrc +file for a +.Ic machine +token that matches the remote machine specified on the +.Nm ftp +command line or as an +.Ic open +command argument. +Once a match is made, the subsequent +.Pa .netrc +tokens are processed, +stopping when the end of file is reached or another +.Ic machine +or a +.Ic default +token is encountered. +.It Ic default +This is the same as +.Ic machine +.Ar name +except that +.Ic default +matches any name. +There can be only one +.Ic default +token, and it must be after all +.Ic machine +tokens. +This is normally used as: +.Pp +.Dl default login anonymous password user@site +.Pp +thereby giving the user +.Ar automatic +anonymous ftp login to +machines not specified in +.Pa .netrc . +This can be overridden +by using the +.Fl n +flag to disable auto-login. +.It Ic login Ar name +Identify a user on the remote machine. +If this token is present, the auto-login process will initiate +a login using the specified +.Ar name . +.It Ic password Ar string +Supply a password. +If this token is present, the auto-login process will supply the +specified string if the remote server requires a password as part +of the login process. +Note that if this token is present in the +.Pa .netrc +file for any user other +than +.Ar anonymous , +.Nm ftp +will abort the auto-login process if the +.Pa .netrc +is readable by +anyone besides the user. +.It Ic account Ar string +Supply an additional account password. +If this token is present, the auto-login process will supply the +specified string if the remote server requires an additional +account password, or the auto-login process will initiate an +.Dv ACCT +command if it does not. +.It Ic macdef Ar name +Define a macro. +This token functions like the +.Nm ftp +.Ic macdef +command functions. +A macro is defined with the specified name; its contents begin with the +next +.Pa .netrc +line and continue until a null line (consecutive new-line +characters) is encountered. +If a macro named +.Ic init +is defined, it is automatically executed as the last step in the +auto-login process. +.El +.Sh ENVIRONMENT +.Nm Ftp +utilizes the following environment variables. +.Bl -tag -width Fl +.It Ev HOME +For default location of a +.Pa .netrc +file, if one exists. +.It Ev SHELL +For default shell. +.El +.Sh SEE ALSO +.Xr ftpd 8 +.Sh HISTORY +The +.Nm ftp +command appeared in +.Bx 4.2 . +.Sh BUGS +Correct execution of many commands depends upon proper behavior +by the remote server. +.Pp +An error in the treatment of carriage returns +in the +.Bx 4.2 +ascii-mode transfer code +has been corrected. +This correction may result in incorrect transfers of binary files +to and from +.Bx 4.2 +servers using the ascii type. +Avoid this problem by using the binary image type. diff --git a/ftp.tproj/ftp.c b/ftp.tproj/ftp.c new file mode 100644 index 0000000..a2a54a9 --- /dev/null +++ b/ftp.tproj/ftp.c @@ -0,0 +1,1542 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ftp_var.h" + +extern int h_errno; + +struct sockaddr_in hisctladdr; +struct sockaddr_in data_addr; +int data = -1; +int abrtflag = 0; +jmp_buf ptabort; +int ptabflg; +int ptflag = 0; +struct sockaddr_in myctladdr; +off_t restart_point = 0; + +FILE *cin, *cout; + +char * +hookup(host, port) + char *host; + int port; +{ + struct hostent *hp = 0; + int s, len, tos; + static char hostnamebuf[80]; + + memset((char *)&hisctladdr, 0, sizeof (hisctladdr)); + hisctladdr.sin_addr.s_addr = inet_addr(host); + if (hisctladdr.sin_addr.s_addr != -1) { + hisctladdr.sin_family = AF_INET; + (void) strncpy(hostnamebuf, host, sizeof(hostnamebuf)); + } else { + hp = gethostbyname(host); + if (hp == NULL) { + warnx("%s: %s", host, hstrerror(h_errno)); + code = -1; + return ((char *) 0); + } + hisctladdr.sin_family = hp->h_addrtype; + memmove((caddr_t)&hisctladdr.sin_addr, + hp->h_addr_list[0], hp->h_length); + (void) strncpy(hostnamebuf, hp->h_name, sizeof(hostnamebuf)); + } + hostname = hostnamebuf; + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + warn("socket"); + code = -1; + return (0); + } + hisctladdr.sin_port = port; + while (connect(s, (struct sockaddr *)&hisctladdr, sizeof (hisctladdr)) < 0) { + if (hp && hp->h_addr_list[1]) { + int oerrno = errno; + char *ia; + + ia = inet_ntoa(hisctladdr.sin_addr); + errno = oerrno; + warn("connect to address %s", ia); + hp->h_addr_list++; + memmove((caddr_t)&hisctladdr.sin_addr, + hp->h_addr_list[0], hp->h_length); + fprintf(stdout, "Trying %s...\n", + inet_ntoa(hisctladdr.sin_addr)); + (void) close(s); + s = socket(hisctladdr.sin_family, SOCK_STREAM, 0); + if (s < 0) { + warn("socket"); + code = -1; + return (0); + } + continue; + } + warn("connect"); + code = -1; + goto bad; + } + len = sizeof (myctladdr); + if (getsockname(s, (struct sockaddr *)&myctladdr, &len) < 0) { + warn("getsockname"); + code = -1; + goto bad; + } +#ifdef IP_TOS + tos = IPTOS_LOWDELAY; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); +#endif + cin = fdopen(s, "r"); + cout = fdopen(s, "w"); + if (cin == NULL || cout == NULL) { + warnx("fdopen failed."); + if (cin) + (void) fclose(cin); + if (cout) + (void) fclose(cout); + code = -1; + goto bad; + } + if (verbose) + printf("Connected to %s.\n", hostname); + if (getreply(0) > 2) { /* read startup message from server */ + if (cin) + (void) fclose(cin); + if (cout) + (void) fclose(cout); + code = -1; + goto bad; + } +#ifdef SO_OOBINLINE + { + int on = 1; + + if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) + < 0 && debug) { + warn("setsockopt"); + } + } +#endif /* SO_OOBINLINE */ + + return (hostname); +bad: + (void) close(s); + return ((char *)0); +} + +int +login(host) + char *host; +{ + char tmp[80]; + char *user, *pass, *acct; + int n, aflag = 0; + + user = pass = acct = 0; + if (ruserpass(host, &user, &pass, &acct) < 0) { + code = -1; + return (0); + } + while (user == NULL) { + char *myname = getlogin(); + + if (myname == NULL) { + struct passwd *pp = getpwuid(getuid()); + + if (pp != NULL) + myname = pp->pw_name; + } + if (myname) + printf("Name (%s:%s): ", host, myname); + else + printf("Name (%s): ", host); + (void) fgets(tmp, sizeof(tmp) - 1, stdin); + tmp[strlen(tmp) - 1] = '\0'; + if (*tmp == '\0') + user = myname; + else + user = tmp; + } + n = command("USER %s", user); + if (n == CONTINUE) { + if (pass == NULL) + pass = getpass("Password:"); + n = command("PASS %s", pass); + } + if (n == CONTINUE) { + aflag++; + acct = getpass("Account:"); + n = command("ACCT %s", acct); + } + if (n != COMPLETE) { + warnx("Login failed."); + return (0); + } + if (!aflag && acct != NULL) + (void) command("ACCT %s", acct); + if (proxy) + return (1); + for (n = 0; n < macnum; ++n) { + if (!strcmp("init", macros[n].mac_name)) { + (void) strcpy(line, "$init"); + makeargv(); + domacro(margc, margv); + break; + } + } + return (1); +} + +void +cmdabort() +{ + + printf("\n"); + (void) fflush(stdout); + abrtflag++; + if (ptflag) + longjmp(ptabort,1); +} + +int command(const char *fmt, ...) +{ + va_list ap; + int r; + sig_t oldintr; + + abrtflag = 0; + if (debug) { + printf("---> "); + va_start(ap, fmt); + if (strncmp("PASS ", fmt, 5) == 0) + printf("PASS XXXX"); + else + vfprintf(stdout, fmt, ap); + va_end(ap); + printf("\n"); + (void) fflush(stdout); + } + if (cout == NULL) { + warn("No control connection for command"); + code = -1; + return (0); + } + oldintr = signal(SIGINT, cmdabort); + va_start(ap, fmt); + vfprintf(cout, fmt, ap); + va_end(ap); + fprintf(cout, "\r\n"); + (void) fflush(cout); + cpend = 1; + r = getreply(!strcmp(fmt, "QUIT")); + if (abrtflag && oldintr != SIG_IGN) + (*oldintr)(SIGINT); + (void) signal(SIGINT, oldintr); + return (r); +} + +char reply_string[BUFSIZ]; /* last line of previous reply */ + +int +getreply(expecteof) + int expecteof; +{ + int c, n; + int dig; + int originalcode = 0, continuation = 0; + sig_t oldintr; + int pflag = 0; + char *cp, *pt = pasv; + + oldintr = signal(SIGINT, cmdabort); + for (;;) { + dig = n = code = 0; + cp = reply_string; + while ((c = getc(cin)) != '\n') { + if (c == IAC) { /* handle telnet commands */ + switch (c = getc(cin)) { + case WILL: + case WONT: + c = getc(cin); + fprintf(cout, "%c%c%c", IAC, DONT, c); + (void) fflush(cout); + break; + case DO: + case DONT: + c = getc(cin); + fprintf(cout, "%c%c%c", IAC, WONT, c); + (void) fflush(cout); + break; + default: + break; + } + continue; + } + dig++; + if (c == EOF) { + if (expecteof) { + (void) signal(SIGINT,oldintr); + code = 221; + return (0); + } + lostpeer(); + if (verbose) { + printf("421 Service not available, remote server has closed connection\n"); + (void) fflush(stdout); + } + code = 421; + return (4); + } + if (c != '\r' && (verbose > 0 || + (verbose > -1 && n == '5' && dig > 4))) { + if (proxflag && + (dig == 1 || dig == 5 && verbose == 0)) + printf("%s:",hostname); + (void) putchar(c); + } + if (dig < 4 && isdigit(c)) + code = code * 10 + (c - '0'); + if (!pflag && code == 227) + pflag = 1; + if (dig > 4 && pflag == 1 && isdigit(c)) + pflag = 2; + if (pflag == 2) { + if (c != '\r' && c != ')') + *pt++ = c; + else { + *pt = '\0'; + pflag = 3; + } + } + if (dig == 4 && c == '-') { + if (continuation) + code = 0; + continuation++; + } + if (n == 0) + n = c; + if (cp < &reply_string[sizeof(reply_string) - 1]) + *cp++ = c; + } + if (verbose > 0 || verbose > -1 && n == '5') { + (void) putchar(c); + (void) fflush (stdout); + } + if (continuation && code != originalcode) { + if (originalcode == 0) + originalcode = code; + continue; + } + *cp = '\0'; + if (n != '1') + cpend = 0; + (void) signal(SIGINT,oldintr); + if (code == 421 || originalcode == 421) + lostpeer(); + if (abrtflag && oldintr != cmdabort && oldintr != SIG_IGN) + (*oldintr)(SIGINT); + return (n - '0'); + } +} + +int +empty(mask, sec) + struct fd_set *mask; + int sec; +{ + struct timeval t; + + t.tv_sec = (long) sec; + t.tv_usec = 0; + return (select(32, mask, (struct fd_set *) 0, (struct fd_set *) 0, &t)); +} + +jmp_buf sendabort; + +void +abortsend() +{ + + mflag = 0; + abrtflag = 0; + printf("\nsend aborted\nwaiting for remote to finish abort\n"); + (void) fflush(stdout); + longjmp(sendabort, 1); +} + +#define HASHBYTES 1024 + +void +sendrequest(cmd, local, remote, printnames) + char *cmd, *local, *remote; + int printnames; +{ + struct stat st; + struct timeval start, stop; + int c, d; + FILE *fin, *dout = 0, *popen(); + int (*closefunc) __P((FILE *)); + sig_t oldintr, oldintp; + long bytes = 0, hashbytes = HASHBYTES; + char *lmode, buf[BUFSIZ], *bufp; + + if (verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + } + if (proxy) { + proxtrans(cmd, local, remote); + return; + } + if (curtype != type) + changetype(type, 0); + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + lmode = "w"; + if (setjmp(sendabort)) { + while (cpend) { + (void) getreply(0); + } + if (data >= 0) { + (void) close(data); + data = -1; + } + if (oldintr) + (void) signal(SIGINT,oldintr); + if (oldintp) + (void) signal(SIGPIPE,oldintp); + code = -1; + return; + } + oldintr = signal(SIGINT, abortsend); + if (strcmp(local, "-") == 0) + fin = stdin; + else if (*local == '|') { + oldintp = signal(SIGPIPE,SIG_IGN); + fin = popen(local + 1, "r"); + if (fin == NULL) { + warn("%s", local + 1); + (void) signal(SIGINT, oldintr); + (void) signal(SIGPIPE, oldintp); + code = -1; + return; + } + closefunc = pclose; + } else { + fin = fopen(local, "r"); + if (fin == NULL) { + warn("local: %s", local); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + closefunc = fclose; + if (fstat(fileno(fin), &st) < 0 || + (st.st_mode&S_IFMT) != S_IFREG) { + fprintf(stdout, "%s: not a plain file.\n", local); + (void) signal(SIGINT, oldintr); + fclose(fin); + code = -1; + return; + } + } + if (initconn()) { + (void) signal(SIGINT, oldintr); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + code = -1; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + if (setjmp(sendabort)) + goto abort; + + if (restart_point && + (strcmp(cmd, "STOR") == 0 || strcmp(cmd, "APPE") == 0)) { + int rc; + + switch (curtype) { + case TYPE_A: + rc = fseek(fin, (long) restart_point, SEEK_SET); + break; + case TYPE_I: + case TYPE_L: + rc = lseek(fileno(fin), restart_point, SEEK_SET); + break; + } + if (rc < 0) { + warn("local: %s", local); + restart_point = 0; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + if (command("REST %ld", (long) restart_point) + != CONTINUE) { + restart_point = 0; + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + restart_point = 0; + lmode = "r+w"; + } + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) { + (void) signal(SIGINT, oldintr); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + } else + if (command("%s", cmd) != PRELIM) { + (void) signal(SIGINT, oldintr); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + if (closefunc != NULL) + (*closefunc)(fin); + return; + } + dout = dataconn(lmode); + if (dout == NULL) + goto abort; + (void) gettimeofday(&start, (struct timezone *)0); + oldintp = signal(SIGPIPE, SIG_IGN); + switch (curtype) { + + case TYPE_I: + case TYPE_L: + errno = d = 0; + while ((c = read(fileno(fin), buf, sizeof (buf))) > 0) { + bytes += c; + for (bufp = buf; c > 0; c -= d, bufp += d) + if ((d = write(fileno(dout), bufp, c)) <= 0) + break; + if (hash) { + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); + } + } + if (hash && bytes > 0) { + if (bytes < HASHBYTES) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (c < 0) + warn("local: %s", local); + if (d < 0) { + if (errno != EPIPE) + warn("netout"); + bytes = -1; + } + break; + + case TYPE_A: + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + while (hash && (bytes >= hashbytes)) { + (void) putchar('#'); + (void) fflush(stdout); + hashbytes += HASHBYTES; + } + if (ferror(dout)) + break; + (void) putc('\r', dout); + bytes++; + } + (void) putc(c, dout); + bytes++; + /* if (c == '\r') { */ + /* (void) putc('\0', dout); // this violates rfc */ + /* bytes++; */ + /* } */ + } + if (hash) { + if (bytes < hashbytes) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (ferror(fin)) + warn("local: %s", local); + if (ferror(dout)) { + if (errno != EPIPE) + warn("netout"); + bytes = -1; + } + break; + } + if (closefunc != NULL) + (*closefunc)(fin); + (void) fclose(dout); + (void) gettimeofday(&stop, (struct timezone *)0); + (void) getreply(0); + (void) signal(SIGINT, oldintr); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); + return; +abort: + (void) signal(SIGINT, oldintr); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + if (!cpend) { + code = -1; + return; + } + if (data >= 0) { + (void) close(data); + data = -1; + } + if (dout) + (void) fclose(dout); + (void) getreply(0); + code = -1; + if (closefunc != NULL && fin != NULL) + (*closefunc)(fin); + (void) gettimeofday(&stop, (struct timezone *)0); + if (bytes > 0) + ptransfer("sent", bytes, &start, &stop); +} + +jmp_buf recvabort; + +void +abortrecv() +{ + + mflag = 0; + abrtflag = 0; + printf("\nreceive aborted\nwaiting for remote to finish abort\n"); + (void) fflush(stdout); + longjmp(recvabort, 1); +} + +void +recvrequest(cmd, local, remote, lmode, printnames) + char *cmd, *local, *remote, *lmode; + int printnames; +{ + FILE *fout, *din = 0; + int (*closefunc) __P((FILE *)); + sig_t oldintr, oldintp; + int c, d, is_retr, tcrflag, bare_lfs = 0; + static int bufsize; + static char *buf; + long bytes = 0, hashbytes = HASHBYTES; + struct timeval start, stop; + struct stat st; + + is_retr = strcmp(cmd, "RETR") == 0; + if (is_retr && verbose && printnames) { + if (local && *local != '-') + printf("local: %s ", local); + if (remote) + printf("remote: %s\n", remote); + } + if (proxy && is_retr) { + proxtrans(cmd, local, remote); + return; + } + closefunc = NULL; + oldintr = NULL; + oldintp = NULL; + tcrflag = !crflag && is_retr; + if (setjmp(recvabort)) { + while (cpend) { + (void) getreply(0); + } + if (data >= 0) { + (void) close(data); + data = -1; + } + if (oldintr) + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + oldintr = signal(SIGINT, abortrecv); + if (strcmp(local, "-") && *local != '|') { + if (access(local, 2) < 0) { + char *dir = strrchr(local, '/'); + + if (errno != ENOENT && errno != EACCES) { + warn("local: %s", local); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (dir != NULL) + *dir = 0; + d = access(dir ? local : ".", 2); + if (dir != NULL) + *dir = '/'; + if (d < 0) { + warn("local: %s", local); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (!runique && errno == EACCES && + chmod(local, 0600) < 0) { + warn("local: %s", local); + (void) signal(SIGINT, oldintr); + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (runique && errno == EACCES && + (local = gunique(local)) == NULL) { + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + } + else if (runique && (local = gunique(local)) == NULL) { + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + } + if (!is_retr) { + if (curtype != TYPE_A) + changetype(TYPE_A, 0); + } else if (curtype != type) + changetype(type, 0); + if (initconn()) { + (void) signal(SIGINT, oldintr); + code = -1; + return; + } + if (setjmp(recvabort)) + goto abort; + if (is_retr && restart_point && + command("REST %ld", (long) restart_point) != CONTINUE) + return; + if (remote) { + if (command("%s %s", cmd, remote) != PRELIM) { + (void) signal(SIGINT, oldintr); + return; + } + } else { + if (command("%s", cmd) != PRELIM) { + (void) signal(SIGINT, oldintr); + return; + } + } + din = dataconn("r"); + if (din == NULL) + goto abort; + if (strcmp(local, "-") == 0) + fout = stdout; + else if (*local == '|') { + oldintp = signal(SIGPIPE, SIG_IGN); + fout = popen(local + 1, "w"); + if (fout == NULL) { + warn("%s", local+1); + goto abort; + } + closefunc = pclose; + } else { + fout = fopen(local, lmode); + if (fout == NULL) { + warn("local: %s", local); + goto abort; + } + closefunc = fclose; + } + if (fstat(fileno(fout), &st) < 0 || st.st_blksize == 0) + st.st_blksize = BUFSIZ; + if (st.st_blksize > bufsize) { + if (buf) + (void) free(buf); + buf = malloc((unsigned)st.st_blksize); + if (buf == NULL) { + warn("malloc"); + bufsize = 0; + goto abort; + } + bufsize = st.st_blksize; + } + (void) gettimeofday(&start, (struct timezone *)0); + switch (curtype) { + + case TYPE_I: + case TYPE_L: + if (restart_point && + lseek(fileno(fout), restart_point, SEEK_SET) < 0) { + warn("local: %s", local); + if (closefunc != NULL) + (*closefunc)(fout); + return; + } + errno = d = 0; + while ((c = read(fileno(din), buf, bufsize)) > 0) { + if ((d = write(fileno(fout), buf, c)) != c) + break; + bytes += c; + if (hash) { + while (bytes >= hashbytes) { + (void) putchar('#'); + hashbytes += HASHBYTES; + } + (void) fflush(stdout); + } + } + if (hash && bytes > 0) { + if (bytes < HASHBYTES) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (c < 0) { + if (errno != EPIPE) + warn("netin"); + bytes = -1; + } + if (d < c) { + if (d < 0) + warn("local: %s", local); + else + warnx("%s: short write", local); + } + break; + + case TYPE_A: + if (restart_point) { + int i, n, ch; + + if (fseek(fout, 0L, SEEK_SET) < 0) + goto done; + n = restart_point; + for (i = 0; i++ < n;) { + if ((ch = getc(fout)) == EOF) + goto done; + if (ch == '\n') + i++; + } + if (fseek(fout, 0L, SEEK_CUR) < 0) { +done: + warn("local: %s", local); + if (closefunc != NULL) + (*closefunc)(fout); + return; + } + } + while ((c = getc(din)) != EOF) { + if (c == '\n') + bare_lfs++; + while (c == '\r') { + while (hash && (bytes >= hashbytes)) { + (void) putchar('#'); + (void) fflush(stdout); + hashbytes += HASHBYTES; + } + bytes++; + if ((c = getc(din)) != '\n' || tcrflag) { + if (ferror(fout)) + goto break2; + (void) putc('\r', fout); + if (c == '\0') { + bytes++; + goto contin2; + } + if (c == EOF) + goto contin2; + } + } + (void) putc(c, fout); + bytes++; + contin2: ; + } +break2: + if (bare_lfs) { + printf("WARNING! %d bare linefeeds received in ASCII mode\n", bare_lfs); + printf("File may not have transferred correctly.\n"); + } + if (hash) { + if (bytes < hashbytes) + (void) putchar('#'); + (void) putchar('\n'); + (void) fflush(stdout); + } + if (ferror(din)) { + if (errno != EPIPE) + warn("netin"); + bytes = -1; + } + if (ferror(fout)) + warn("local: %s", local); + break; + } + if (closefunc != NULL) + (*closefunc)(fout); + (void) signal(SIGINT, oldintr); + if (oldintp) + (void) signal(SIGPIPE, oldintp); + (void) fclose(din); + (void) gettimeofday(&stop, (struct timezone *)0); + (void) getreply(0); + if (bytes > 0 && is_retr) + ptransfer("received", bytes, &start, &stop); + return; +abort: + +/* abort using RFC959 recommended IP,SYNC sequence */ + + if (oldintp) + (void) signal(SIGPIPE, oldintr); + (void) signal(SIGINT, SIG_IGN); + if (!cpend) { + code = -1; + (void) signal(SIGINT, oldintr); + return; + } + + abort_remote(din); + code = -1; + if (data >= 0) { + (void) close(data); + data = -1; + } + if (closefunc != NULL && fout != NULL) + (*closefunc)(fout); + if (din) + (void) fclose(din); + (void) gettimeofday(&stop, (struct timezone *)0); + if (bytes > 0) + ptransfer("received", bytes, &start, &stop); + (void) signal(SIGINT, oldintr); +} + +/* + * Need to start a listen on the data channel before we send the command, + * otherwise the server's connect may fail. + */ +int +initconn() +{ + char *p, *a; + int result, len, tmpno = 0; + int on = 1; + int a0, a1, a2, a3, p0, p1; + + if (passivemode) { + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + perror("ftp: socket"); + return(1); + } + if ((options & SO_DEBUG) && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, + sizeof (on)) < 0) + perror("ftp: setsockopt (ignored)"); + if (command("PASV") != COMPLETE) { + printf("Passive mode refused.\n"); + goto bad; + } + + /* + * What we've got at this point is a string of comma + * separated one-byte unsigned integer values. + * The first four are the an IP address. The fifth is + * the MSB of the port number, the sixth is the LSB. + * From that we'll prepare a sockaddr_in. + */ + + if (sscanf(pasv,"%d,%d,%d,%d,%d,%d", + &a0, &a1, &a2, &a3, &p0, &p1) != 6) { + printf("Passive mode address scan failure. " + "Shouldn't happen!\n"); + goto bad; + } + + bzero(&data_addr, sizeof(data_addr)); + data_addr.sin_family = AF_INET; + a = (char *)&data_addr.sin_addr.s_addr; + a[0] = a0 & 0xff; + a[1] = a1 & 0xff; + a[2] = a2 & 0xff; + a[3] = a3 & 0xff; + p = (char *)&data_addr.sin_port; + p[0] = p0 & 0xff; + p[1] = p1 & 0xff; + + if (connect(data, (struct sockaddr *)&data_addr, + sizeof(data_addr)) < 0) { + perror("ftp: connect"); + goto bad; + } +#ifdef IP_TOS + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, + sizeof(int)) < 0) + perror("ftp: setsockopt TOS (ignored)"); +#endif + return(0); + } + +noport: + data_addr = myctladdr; + if (sendport) + data_addr.sin_port = 0; /* let system pick one */ + if (data != -1) + (void) close(data); + data = socket(AF_INET, SOCK_STREAM, 0); + if (data < 0) { + warn("socket"); + if (tmpno) + sendport = 1; + return (1); + } + if (!sendport) + if (setsockopt(data, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)) < 0) { + warn("setsockopt (reuse address)"); + goto bad; + } + if (bind(data, (struct sockaddr *)&data_addr, sizeof (data_addr)) < 0) { + warn("bind"); + goto bad; + } + if (options & SO_DEBUG && + setsockopt(data, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof (on)) < 0) + warn("setsockopt (ignored)"); + len = sizeof (data_addr); + if (getsockname(data, (struct sockaddr *)&data_addr, &len) < 0) { + warn("getsockname"); + goto bad; + } + if (listen(data, 1) < 0) + warn("listen"); + if (sendport) { + a = (char *)&data_addr.sin_addr; + p = (char *)&data_addr.sin_port; +#define UC(b) (((int)b)&0xff) + result = + command("PORT %d,%d,%d,%d,%d,%d", + UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), + UC(p[0]), UC(p[1])); + if (result == ERROR && sendport == -1) { + sendport = 0; + tmpno = 1; + goto noport; + } + return (result != COMPLETE); + } + if (tmpno) + sendport = 1; +#ifdef IP_TOS + on = IPTOS_THROUGHPUT; + if (setsockopt(data, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); +#endif + return (0); +bad: + (void) close(data), data = -1; + if (tmpno) + sendport = 1; + return (1); +} + +FILE * +dataconn(lmode) + char *lmode; +{ + struct sockaddr_in from; + int s, fromlen = sizeof (from), tos; + + if (passivemode) + return (fdopen(data, lmode)); + + s = accept(data, (struct sockaddr *) &from, &fromlen); + if (s < 0) { + warn("accept"); + (void) close(data), data = -1; + return (NULL); + } + (void) close(data); + data = s; +#ifdef IP_TOS + tos = IPTOS_THROUGHPUT; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); +#endif + return (fdopen(data, lmode)); +} + +void +ptransfer(direction, bytes, t0, t1) + char *direction; + long bytes; + struct timeval *t0, *t1; +{ + struct timeval td; + float s; + long bs; + + if (verbose) { + tvsub(&td, t1, t0); + s = td.tv_sec + (td.tv_usec / 1000000.); +#define nz(x) ((x) == 0 ? 1 : (x)) + bs = bytes / nz(s); + printf("%ld bytes %s in %.3g seconds (%ld bytes/s)\n", + bytes, direction, s, bs); + } +} + +/* +void +tvadd(tsum, t0) + struct timeval *tsum, *t0; +{ + + tsum->tv_sec += t0->tv_sec; + tsum->tv_usec += t0->tv_usec; + if (tsum->tv_usec > 1000000) + tsum->tv_sec++, tsum->tv_usec -= 1000000; +} +*/ + +void +tvsub(tdiff, t1, t0) + struct timeval *tdiff, *t1, *t0; +{ + + tdiff->tv_sec = t1->tv_sec - t0->tv_sec; + tdiff->tv_usec = t1->tv_usec - t0->tv_usec; + if (tdiff->tv_usec < 0) + tdiff->tv_sec--, tdiff->tv_usec += 1000000; +} + +void +psabort() +{ + + abrtflag++; +} + +void +pswitch(flag) + int flag; +{ + sig_t oldintr; + static struct comvars { + int connect; + char name[MAXHOSTNAMELEN]; + struct sockaddr_in mctl; + struct sockaddr_in hctl; + FILE *in; + FILE *out; + int tpe; + int curtpe; + int cpnd; + int sunqe; + int runqe; + int mcse; + int ntflg; + char nti[17]; + char nto[17]; + int mapflg; + char mi[MAXPATHLEN]; + char mo[MAXPATHLEN]; + } proxstruct, tmpstruct; + struct comvars *ip, *op; + + abrtflag = 0; + oldintr = signal(SIGINT, psabort); + if (flag) { + if (proxy) + return; + ip = &tmpstruct; + op = &proxstruct; + proxy++; + } else { + if (!proxy) + return; + ip = &proxstruct; + op = &tmpstruct; + proxy = 0; + } + ip->connect = connected; + connected = op->connect; + if (hostname) { + (void) strncpy(ip->name, hostname, sizeof(ip->name) - 1); + ip->name[strlen(ip->name)] = '\0'; + } else + ip->name[0] = 0; + hostname = op->name; + ip->hctl = hisctladdr; + hisctladdr = op->hctl; + ip->mctl = myctladdr; + myctladdr = op->mctl; + ip->in = cin; + cin = op->in; + ip->out = cout; + cout = op->out; + ip->tpe = type; + type = op->tpe; + ip->curtpe = curtype; + curtype = op->curtpe; + ip->cpnd = cpend; + cpend = op->cpnd; + ip->sunqe = sunique; + sunique = op->sunqe; + ip->runqe = runique; + runique = op->runqe; + ip->mcse = mcase; + mcase = op->mcse; + ip->ntflg = ntflag; + ntflag = op->ntflg; + (void) strncpy(ip->nti, ntin, 16); + (ip->nti)[strlen(ip->nti)] = '\0'; + (void) strcpy(ntin, op->nti); + (void) strncpy(ip->nto, ntout, 16); + (ip->nto)[strlen(ip->nto)] = '\0'; + (void) strcpy(ntout, op->nto); + ip->mapflg = mapflag; + mapflag = op->mapflg; + (void) strncpy(ip->mi, mapin, MAXPATHLEN - 1); + (ip->mi)[strlen(ip->mi)] = '\0'; + (void) strcpy(mapin, op->mi); + (void) strncpy(ip->mo, mapout, MAXPATHLEN - 1); + (ip->mo)[strlen(ip->mo)] = '\0'; + (void) strcpy(mapout, op->mo); + (void) signal(SIGINT, oldintr); + if (abrtflag) { + abrtflag = 0; + (*oldintr)(SIGINT); + } +} + +void +abortpt() +{ + + printf("\n"); + (void) fflush(stdout); + ptabflg++; + mflag = 0; + abrtflag = 0; + longjmp(ptabort, 1); +} + +void +proxtrans(cmd, local, remote) + char *cmd, *local, *remote; +{ + sig_t oldintr; + int secndflag = 0, prox_type, nfnd; + char *cmd2; + struct fd_set mask; + + if (strcmp(cmd, "RETR")) + cmd2 = "RETR"; + else + cmd2 = runique ? "STOU" : "STOR"; + if ((prox_type = type) == 0) { + if (unix_server && unix_proxy) + prox_type = TYPE_I; + else + prox_type = TYPE_A; + } + if (curtype != prox_type) + changetype(prox_type, 1); + if (command("PASV") != COMPLETE) { + printf("proxy server does not support third party transfers.\n"); + return; + } + pswitch(0); + if (!connected) { + printf("No primary connection\n"); + pswitch(1); + code = -1; + return; + } + if (curtype != prox_type) + changetype(prox_type, 1); + if (command("PORT %s", pasv) != COMPLETE) { + pswitch(1); + return; + } + if (setjmp(ptabort)) + goto abort; + oldintr = signal(SIGINT, abortpt); + if (command("%s %s", cmd, remote) != PRELIM) { + (void) signal(SIGINT, oldintr); + pswitch(1); + return; + } + sleep(2); + pswitch(1); + secndflag++; + if (command("%s %s", cmd2, local) != PRELIM) + goto abort; + ptflag++; + (void) getreply(0); + pswitch(0); + (void) getreply(0); + (void) signal(SIGINT, oldintr); + pswitch(1); + ptflag = 0; + printf("local: %s remote: %s\n", local, remote); + return; +abort: + (void) signal(SIGINT, SIG_IGN); + ptflag = 0; + if (strcmp(cmd, "RETR") && !proxy) + pswitch(1); + else if (!strcmp(cmd, "RETR") && proxy) + pswitch(0); + if (!cpend && !secndflag) { /* only here if cmd = "STOR" (proxy=1) */ + if (command("%s %s", cmd2, local) != PRELIM) { + pswitch(0); + if (cpend) + abort_remote((FILE *) NULL); + } + pswitch(1); + if (ptabflg) + code = -1; + (void) signal(SIGINT, oldintr); + return; + } + if (cpend) + abort_remote((FILE *) NULL); + pswitch(!proxy); + if (!cpend && !secndflag) { /* only if cmd = "RETR" (proxy=1) */ + if (command("%s %s", cmd2, local) != PRELIM) { + pswitch(0); + if (cpend) + abort_remote((FILE *) NULL); + pswitch(1); + if (ptabflg) + code = -1; + (void) signal(SIGINT, oldintr); + return; + } + } + if (cpend) + abort_remote((FILE *) NULL); + pswitch(!proxy); + if (cpend) { + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask, 10)) <= 0) { + if (nfnd < 0) { + warn("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + (void) getreply(0); + (void) getreply(0); + } + if (proxy) + pswitch(0); + pswitch(1); + if (ptabflg) + code = -1; + (void) signal(SIGINT, oldintr); +} + +void +reset(argc, argv) + int argc; + char *argv[]; +{ + struct fd_set mask; + int nfnd = 1; + + FD_ZERO(&mask); + while (nfnd > 0) { + FD_SET(fileno(cin), &mask); + if ((nfnd = empty(&mask,0)) < 0) { + warn("reset"); + code = -1; + lostpeer(); + } + else if (nfnd) { + (void) getreply(0); + } + } +} + +char * +gunique(local) + char *local; +{ + static char new[MAXPATHLEN]; + char *cp = strrchr(local, '/'); + int d, count=0; + char ext = '1'; + + if (cp) + *cp = '\0'; + d = access(cp ? local : ".", 2); + if (cp) + *cp = '/'; + if (d < 0) { + warn("local: %s", local); + return ((char *) 0); + } + (void) strcpy(new, local); + cp = new + strlen(new); + *cp++ = '.'; + while (!d) { + if (++count == 100) { + printf("runique: can't find unique file name.\n"); + return ((char *) 0); + } + *cp++ = ext; + *cp = '\0'; + if (ext == '9') + ext = '0'; + else + ext++; + if ((d = access(new, 0)) < 0) + break; + if (ext != '0') + cp--; + else if (*(cp - 2) == '.') + *(cp - 1) = '1'; + else { + *(cp - 2) = *(cp - 2) + 1; + cp--; + } + } + return (new); +} + +void +abort_remote(din) + FILE *din; +{ + char buf[BUFSIZ]; + int nfnd; + struct fd_set mask; + + /* + * send IAC in urgent mode instead of DM because 4.3BSD places oob mark + * after urgent byte rather than before as is protocol now + */ + sprintf(buf, "%c%c%c", IAC, IP, IAC); + if (send(fileno(cout), buf, 3, MSG_OOB) != 3) + warn("abort"); + fprintf(cout,"%cABOR\r\n", DM); + (void) fflush(cout); + FD_ZERO(&mask); + FD_SET(fileno(cin), &mask); + if (din) { + FD_SET(fileno(din), &mask); + } + if ((nfnd = empty(&mask, 10)) <= 0) { + if (nfnd < 0) { + warn("abort"); + } + if (ptabflg) + code = -1; + lostpeer(); + } + if (din && FD_ISSET(fileno(din), &mask)) { + while (read(fileno(din), buf, BUFSIZ) > 0) + /* LOOP */; + } + if (getreply(0) == ERROR && code == 552) { + /* 552 needed for nic style abort */ + (void) getreply(0); + } + (void) getreply(0); +} diff --git a/ftp.tproj/ftp_var.c b/ftp.tproj/ftp_var.c new file mode 100644 index 0000000..f1f972b --- /dev/null +++ b/ftp.tproj/ftp_var.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftp_var.h 8.4 (Berkeley) 10/9/94 + */ + +#include + +#include "ftp_var.h" + +/* + * FTP global variables. + */ + +#include +#include + +#include "extern.h" + +/* + * Options and other state info. + */ +int trace; /* trace packets exchanged */ +int hash; /* print # for each buffer transferred */ +int sendport; /* use PORT cmd for each data connection */ +int verbose; /* print messages coming back from server */ +int connected; /* connected to server */ +int fromatty; /* input is from a terminal */ +int interactive; /* interactively prompt on m* cmds */ +int debug; /* debugging level */ +int bell; /* ring bell on cmd completion */ +int doglob; /* glob local file names */ +int autologin; /* establish user account on connection */ +int proxy; /* proxy server connection active */ +int proxflag; /* proxy connection exists */ +int sunique; /* store files on server with unique name */ +int runique; /* store local files with unique name */ +int mcase; /* map upper to lower case for mget names */ +int ntflag; /* use ntin ntout tables for name translation */ +int mapflag; /* use mapin mapout templates on file names */ +int code; /* return/reply code for ftp command */ +int crflag; /* if 1, strip car. rets. on ascii gets */ +char pasv[64]; /* passive port for proxy data connection */ +int passivemode; /* passive mode enabled */ +char *altarg; /* argv[1] with no shell-like preprocessing */ +char ntin[17]; /* input translation table */ +char ntout[17]; /* output translation table */ +char mapin[MAXPATHLEN]; /* input map template */ +char mapout[MAXPATHLEN]; /* output map template */ +char typename[32]; /* name of file transfer type */ +int type; /* requested file transfer type */ +int curtype; /* current file transfer type */ +char structname[32]; /* name of file transfer structure */ +int stru; /* file transfer structure */ +char formname[32]; /* name of file transfer format */ +int form; /* file transfer format */ +char modename[32]; /* name of file transfer mode */ +int mode; /* file transfer mode */ +char bytename[32]; /* local byte size in ascii */ +int bytesize; /* local byte size in binary */ + +char *hostname; /* name of host connected to */ +int unix_server; /* server is unix, can use binary for ascii */ +int unix_proxy; /* proxy is unix, can use binary for ascii */ + +struct servent *sp; /* service spec for tcp/ftp */ + +jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ + +char line[200]; /* input line buffer */ +char *stringbase; /* current scan point in line buffer */ +char argbuf[200]; /* argument storage buffer */ +char *argbase; /* current storage point in arg buffer */ +int margc; /* count of arguments on input line */ +char *margv[20]; /* args parsed from input line */ +int cpend; /* flag: if != 0, then pending server reply */ +int mflag; /* flag: if != 0, then active multi command */ + +int options; /* used during socket creation */ + +int macnum; /* number of defined macros */ +struct macel macros[16]; +char macbuf[4096]; diff --git a/ftp.tproj/ftp_var.h b/ftp.tproj/ftp_var.h new file mode 100644 index 0000000..ad7f790 --- /dev/null +++ b/ftp.tproj/ftp_var.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftp_var.h 8.4 (Berkeley) 10/9/94 + */ + +/* + * FTP global variables. + */ + +#include +#include + +#include "extern.h" + +/* + * Options and other state info. + */ +extern int trace; /* trace packets exchanged */ +extern int hash; /* pr int # for each buffer transferred */ +extern int sendport; /* use PORT cmd for each data connection */ +extern int verbose; /* print messages coming back from server */ +extern int connected; /* connected to server */ +extern int fromatty; /* input is from a terminal */ +extern int interactive; /* interactively prompt on m* cmds */ +extern int debug; /* debugging level */ +extern int bell; /* ring bell on cmd completion */ +extern int doglob; /* glob local file names */ +extern int autologin; /* establish user account on connection */ +extern int proxy; /* proxy server connection active */ +extern int proxflag; /* proxy connection exists */ +extern int sunique; /* store files on server with unique name */ +extern int runique; /* store local files with unique name */ +extern int mcase; /* map upper to lower case for mget names */ +extern int ntflag; /* use ntin ntout tables for name translation */ +extern int mapflag; /* use mapin mapout templates on file names */ +extern int code; /* return/reply code for ftp command */ +extern int crflag; /* if 1, strip car. rets. on ascii gets */ +extern char pasv[64]; /* passive port for proxy data connection */ +extern int passivemode; /* passive mode enabled */ +extern char *altarg; /* argv[1] with no shell-like preprocessing */ +extern char ntin[17]; /* input translation table */ +extern char ntout[17]; /* output translation table */ +extern char mapin[MAXPATHLEN]; /* input map template */ +extern char mapout[MAXPATHLEN]; /* output map template */ +extern char typename[32]; /* name of file transfer type */ +extern int type; /* requested file transfer type */ +extern int curtype; /* current file transfer type */ +extern char structname[32]; /* name of file transfer structure */ +extern int stru; /* file transfer structure */ +extern char formname[32]; /* name of file transfer format */ +extern int form; /* file transfer format */ +extern char modename[32]; /* name of file transfer mode */ +extern int mode; /* file transfer mode */ +extern char bytename[32]; /* local byte size in ascii */ +extern int bytesize; /* local byte size in binary */ + +extern char *hostname; /* name of host connected to */ +extern int unix_server; /* server is unix, can use binary for ascii */ +extern int unix_proxy; /* proxy is unix, can use binary for ascii */ + +extern struct servent *sp; /* service spec for tcp/ftp */ + +extern jmp_buf toplevel; /* non-local goto stuff for cmd scanner */ + +extern char line[200]; /* input line buffer */ +extern char *stringbase; /* current scan point in line buffer */ +extern char argbuf[200]; /* argument storage buffer */ +extern char *argbase; /* current storage point in arg buffer */ +extern int margc; /* count of arguments on input line */ +extern char *margv[20]; /* args parsed from input line */ +extern int cpend; /* flag: if != 0, then pending server reply */ +extern int mflag; /* flag: if != 0, then active multi command */ + +extern int options; /* used during socket creation */ + +/* + * Format of command table. + */ +struct cmd { + char *c_name; /* name of command */ + char *c_help; /* help string */ + char c_bell; /* give bell when command completes */ + char c_conn; /* must be connected to use command */ + char c_proxy; /* proxy server may execute */ + void (*c_handler) __P((int, char **)); /* function to call */ +}; + +struct macel { + char mac_name[9]; /* macro name */ + char *mac_start; /* start of macro in macbuf */ + char *mac_end; /* end of macro in macbuf */ +}; + +extern int macnum; /* number of defined macros */ +extern struct macel macros[16]; +extern char macbuf[4096]; diff --git a/ftp.tproj/h.template b/ftp.tproj/h.template new file mode 100644 index 0000000..f3c1b04 --- /dev/null +++ b/ftp.tproj/h.template @@ -0,0 +1,11 @@ +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import + +@interface $FILENAMESANSEXTENSION$ : NSObject +{ + +} + +@end diff --git a/ftp.tproj/m.template b/ftp.tproj/m.template new file mode 100644 index 0000000..1216fe5 --- /dev/null +++ b/ftp.tproj/m.template @@ -0,0 +1,18 @@ +$$ Lines starting with $$ are not inserted into newly created files +$$ The following substitutions are made: +$$ +$$ $FILENAME$ e.g. foo.m +$$ $FILENAMESANSEXTENSION$ e.g. foo +$$ $DIRECTORY$ e.g. /tmp/MyNewApp +$$ $PROJECTNAME$ e.g. MyNewApp +$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj +$$ $USERNAME$ e.g. mwagner +$$ $DATE$ e.g. Jan-1-1994 +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import "$FILENAMESANSEXTENSION$.h" + +@implementation $FILENAMESANSEXTENSION$ + +@end diff --git a/ftp.tproj/main.c b/ftp.tproj/main.c new file mode 100644 index 0000000..4ad3ed2 --- /dev/null +++ b/ftp.tproj/main.c @@ -0,0 +1,528 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * FTP User Program -- Command Interface. + */ +/*#include */ +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ftp_var.h" + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch, top; + struct passwd *pw = NULL; + char *cp, homedir[MAXPATHLEN]; + + sp = getservbyname("ftp", "tcp"); + if (sp == 0) + errx(1, "ftp/tcp: unknown service"); + doglob = 1; + interactive = 1; + autologin = 1; + + while ((ch = getopt(argc, argv, "dgintv")) != EOF) { + switch (ch) { + case 'd': + options |= SO_DEBUG; + debug++; + break; + + case 'g': + doglob = 0; + break; + + case 'i': + interactive = 0; + break; + + case 'n': + autologin = 0; + break; + + case 't': + trace++; + break; + + case 'v': + verbose++; + break; + + default: + (void)fprintf(stderr, + "usage: ftp [-dgintv] [host [port]]\n"); + exit(1); + } + } + argc -= optind; + argv += optind; + + fromatty = isatty(fileno(stdin)); + if (fromatty) + verbose++; + cpend = 0; /* no pending replies */ + proxy = 0; /* proxy not active */ + passivemode = 0; /* passive mode not active */ + crflag = 1; /* strip c.r. on ascii gets */ + sendport = -1; /* not using ports */ + /* + * Set up the home directory in case we're globbing. + */ + cp = getlogin(); + if (cp != NULL) { + pw = getpwnam(cp); + } + if (pw == NULL) + pw = getpwuid(getuid()); + if (pw != NULL) { + home = homedir; + (void) strcpy(home, pw->pw_dir); + } + if (argc > 0) { + char *xargv[5]; + extern char *__progname; + + if (setjmp(toplevel)) + exit(0); + (void) signal(SIGINT, intr); + (void) signal(SIGPIPE, lostpeer); + xargv[0] = __progname; + xargv[1] = argv[0]; + xargv[2] = argv[1]; + xargv[3] = argv[2]; + xargv[4] = NULL; + setpeer(argc+1, xargv); + } + top = setjmp(toplevel) == 0; + if (top) { + (void) signal(SIGINT, intr); + (void) signal(SIGPIPE, lostpeer); + } + for (;;) { + cmdscanner(top); + top = 1; + } +} + +void +intr() +{ + + longjmp(toplevel, 1); +} + +void +lostpeer() +{ + + if (connected) { + if (cout != NULL) { + (void) shutdown(fileno(cout), 1+1); + (void) fclose(cout); + cout = NULL; + } + if (data >= 0) { + (void) shutdown(data, 1+1); + (void) close(data); + data = -1; + } + connected = 0; + } + pswitch(1); + if (connected) { + if (cout != NULL) { + (void) shutdown(fileno(cout), 1+1); + (void) fclose(cout); + cout = NULL; + } + connected = 0; + } + proxflag = 0; + pswitch(0); +} + +/* +char * +tail(filename) + char *filename; +{ + char *s; + + while (*filename) { + s = strrchr(filename, '/'); + if (s == NULL) + break; + if (s[1]) + return (s + 1); + *s = '\0'; + } + return (filename); +} +*/ + +/* + * Command parser. + */ +void +cmdscanner(top) + int top; +{ + struct cmd *c; + int l; + + if (!top) + (void) putchar('\n'); + for (;;) { + if (fromatty) { + printf("ftp> "); + (void) fflush(stdout); + } + if (fgets(line, sizeof line, stdin) == NULL) + quit(0, 0); + l = strlen(line); + if (l == 0) + break; + if (line[--l] == '\n') { + if (l == 0) + break; + line[l] = '\0'; + } else if (l == sizeof(line) - 2) { + printf("sorry, input line too long\n"); + while ((l = getchar()) != '\n' && l != EOF) + /* void */; + break; + } /* else it was a line without a newline */ + makeargv(); + if (margc == 0) { + continue; + } + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->c_conn && !connected) { + printf("Not connected.\n"); + continue; + } + (*c->c_handler)(margc, margv); + if (bell && c->c_bell) + (void) putchar('\007'); + if (c->c_handler != help) + break; + } + (void) signal(SIGINT, intr); + (void) signal(SIGPIPE, lostpeer); +} + +struct cmd * +getcmd(name) + char *name; +{ + char *p, *q; + struct cmd *c, *found; + int nmatches, longest; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; p = c->c_name; c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return (c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return ((struct cmd *)-1); + return (found); +} + +/* + * Slice a string up into argc/argv. + */ + +int slrflag; + +void +makeargv() +{ + char **argp; + + margc = 0; + argp = margv; + stringbase = line; /* scan from first of buffer */ + argbase = argbuf; /* store from first of buffer */ + slrflag = 0; + while (*argp++ = slurpstring()) + margc++; +} + +/* + * Parse string into argbuf; + * implemented with FSM to + * handle quoting and strings + */ +char * +slurpstring() +{ + int got_one = 0; + char *sb = stringbase; + char *ap = argbase; + char *tmp = argbase; /* will return this if token found */ + + if (*sb == '!' || *sb == '$') { /* recognize ! as a token for shell */ + switch (slrflag) { /* and $ as token for macro invoke */ + case 0: + slrflag++; + stringbase++; + return ((*sb == '!') ? "!" : "$"); + /* NOTREACHED */ + case 1: + slrflag++; + altarg = stringbase; + break; + default: + break; + } + } + +S0: + switch (*sb) { + + case '\0': + goto OUT; + + case ' ': + case '\t': + sb++; goto S0; + + default: + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = sb; + break; + default: + break; + } + goto S1; + } + +S1: + switch (*sb) { + + case ' ': + case '\t': + case '\0': + goto OUT; /* end of token */ + + case '\\': + sb++; goto S2; /* slurp next character */ + + case '"': + sb++; goto S3; /* slurp quoted string */ + + default: + *ap++ = *sb++; /* add character to token */ + got_one = 1; + goto S1; + } + +S2: + switch (*sb) { + + case '\0': + goto OUT; + + default: + *ap++ = *sb++; + got_one = 1; + goto S1; + } + +S3: + switch (*sb) { + + case '\0': + goto OUT; + + case '"': + sb++; goto S1; + + default: + *ap++ = *sb++; + got_one = 1; + goto S3; + } + +OUT: + if (got_one) + *ap++ = '\0'; + argbase = ap; /* update storage pointer */ + stringbase = sb; /* update scan pointer */ + if (got_one) { + return (tmp); + } + switch (slrflag) { + case 0: + slrflag++; + break; + case 1: + slrflag++; + altarg = (char *) 0; + break; + default: + break; + } + return ((char *)0); +} + +#define HELPINDENT ((int) sizeof ("directory")) + +/* + * Help command. + * Call each command handler with argc == 0 and argv[0] == name. + */ +void +help(argc, argv) + int argc; + char *argv[]; +{ + struct cmd *c; + + if (argc == 1) { + int i, j, w, k; + int columns, width = 0, lines; + + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { + int len = strlen(c->c_name); + + if (len > width) + width = len; + } + width = (width + 8) &~ 7; + columns = 80 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + c = cmdtab + j * lines + i; + if (c->c_name && (!proxy || c->c_proxy)) { + printf("%s", c->c_name); + } + else if (c->c_name) { + for (k=0; k < strlen(c->c_name); k++) { + (void) putchar(' '); + } + } + if (c + lines >= &cmdtab[NCMDS]) { + printf("\n"); + break; + } + w = strlen(c->c_name); + while (w < width) { + w = (w + 8) &~ 7; + (void) putchar('\t'); + } + } + } + return; + } + while (--argc > 0) { + char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%-*s\t%s\n", HELPINDENT, + c->c_name, c->c_help); + } +} diff --git a/ftp.tproj/pathnames.h b/ftp.tproj/pathnames.h new file mode 100644 index 0000000..4403aa8 --- /dev/null +++ b/ftp.tproj/pathnames.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +#undef _PATH_TMP +#define _PATH_TMP "/tmp/ftpXXXXXX" diff --git a/ftp.tproj/ruserpass.c b/ftp.tproj/ruserpass.c new file mode 100644 index 0000000..ed5a406 --- /dev/null +++ b/ftp.tproj/ruserpass.c @@ -0,0 +1,300 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "ftp_var.h" + +static int token __P((void)); +static FILE *cfile; + +#define DEFAULT 1 +#define LOGIN 2 +#define PASSWD 3 +#define ACCOUNT 4 +#define MACDEF 5 +#define ID 10 +#define MACH 11 + +static char tokval[100]; + +static struct toktab { + char *tokstr; + int tval; +} toktab[]= { + { "default", DEFAULT }, + { "login", LOGIN }, + { "password", PASSWD }, + { "passwd", PASSWD }, + { "account", ACCOUNT }, + { "machine", MACH }, + { "macdef", MACDEF }, + { NULL, 0 } +}; + +int +ruserpass(host, aname, apass, aacct) + char *host, **aname, **apass, **aacct; +{ + char *hdir, buf[BUFSIZ], *tmp; + char myname[MAXHOSTNAMELEN], *mydomain; + int t, i, c, usedefault = 0; + struct stat stb; + + hdir = getenv("HOME"); + if (hdir == NULL) + hdir = "."; + (void) sprintf(buf, "%s/.netrc", hdir); + cfile = fopen(buf, "r"); + if (cfile == NULL) { + if (errno != ENOENT) + warn("%s", buf); + return (0); + } + if (gethostname(myname, sizeof(myname)) < 0) + myname[0] = '\0'; + if ((mydomain = strchr(myname, '.')) == NULL) + mydomain = ""; +next: + while ((t = token())) switch(t) { + + case DEFAULT: + usedefault = 1; + /* FALL THROUGH */ + + case MACH: + if (!usedefault) { + if (token() != ID) + continue; + /* + * Allow match either for user's input host name + * or official hostname. Also allow match of + * incompletely-specified host in local domain. + */ + if (strcasecmp(host, tokval) == 0) + goto match; + if (strcasecmp(hostname, tokval) == 0) + goto match; + if ((tmp = strchr(hostname, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(hostname, tokval, tmp-hostname) == 0 && + tokval[tmp - hostname] == '\0') + goto match; + if ((tmp = strchr(host, '.')) != NULL && + strcasecmp(tmp, mydomain) == 0 && + strncasecmp(host, tokval, tmp - host) == 0 && + tokval[tmp - host] == '\0') + goto match; + continue; + } + match: + while ((t = token()) && t != MACH && t != DEFAULT) switch(t) { + + case LOGIN: + if (token()) + if (*aname == 0) { + *aname = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*aname, tokval); + } else { + if (strcmp(*aname, tokval)) + goto next; + } + break; + case PASSWD: + if ((*aname == NULL || strcmp(*aname, "anonymous")) && + fstat(fileno(cfile), &stb) >= 0 && + (stb.st_mode & 077) != 0) { + warnx("Error: .netrc file is readable by others."); + warnx("Remove password or make file unreadable by others."); + goto bad; + } + if (token() && *apass == 0) { + *apass = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*apass, tokval); + } + break; + case ACCOUNT: + if (fstat(fileno(cfile), &stb) >= 0 + && (stb.st_mode & 077) != 0) { + warnx("Error: .netrc file is readable by others."); + warnx("Remove account or make file unreadable by others."); + goto bad; + } + if (token() && *aacct == 0) { + *aacct = malloc((unsigned) strlen(tokval) + 1); + (void) strcpy(*aacct, tokval); + } + break; + case MACDEF: + if (proxy) { + (void) fclose(cfile); + return (0); + } + while ((c=getc(cfile)) != EOF && c == ' ' || c == '\t'); + if (c == EOF || c == '\n') { + printf("Missing macdef name argument.\n"); + goto bad; + } + if (macnum == 16) { + printf("Limit of 16 macros have already been defined\n"); + goto bad; + } + tmp = macros[macnum].mac_name; + *tmp++ = c; + for (i=0; i < 8 && (c=getc(cfile)) != EOF && + !isspace(c); ++i) { + *tmp++ = c; + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = '\0'; + if (c != '\n') { + while ((c=getc(cfile)) != EOF && c != '\n'); + } + if (c == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + if (macnum == 0) { + macros[macnum].mac_start = macbuf; + } + else { + macros[macnum].mac_start = macros[macnum-1].mac_end + 1; + } + tmp = macros[macnum].mac_start; + while (tmp != macbuf + 4096) { + if ((c=getc(cfile)) == EOF) { + printf("Macro definition missing null line terminator.\n"); + goto bad; + } + *tmp = c; + if (*tmp == '\n') { + if (*(tmp-1) == '\0') { + macros[macnum++].mac_end = tmp - 1; + break; + } + *tmp = '\0'; + } + tmp++; + } + if (tmp == macbuf + 4096) { + printf("4K macro buffer exceeded\n"); + goto bad; + } + break; + default: + warnx("Unknown .netrc keyword %s", tokval); + break; + } + goto done; + } +done: + (void) fclose(cfile); + return (0); +bad: + (void) fclose(cfile); + return (-1); +} + +static int +token() +{ + char *cp; + int c; + struct toktab *t; + + if (feof(cfile) || ferror(cfile)) + return (0); + while ((c = getc(cfile)) != EOF && + (c == '\n' || c == '\t' || c == ' ' || c == ',')) + continue; + if (c == EOF) + return (0); + cp = tokval; + if (c == '"') { + while ((c = getc(cfile)) != EOF && c != '"') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } else { + *cp++ = c; + while ((c = getc(cfile)) != EOF + && c != '\n' && c != '\t' && c != ' ' && c != ',') { + if (c == '\\') + c = getc(cfile); + *cp++ = c; + } + } + *cp = 0; + if (tokval[0] == 0) + return (0); + for (t = toktab; t->tokstr; t++) + if (!strcmp(t->tokstr, tokval)) + return (t->tval); + return (ID); +} diff --git a/ftpd.tproj/Makefile b/ftpd.tproj/Makefile new file mode 100644 index 0000000..a1d09f3 --- /dev/null +++ b/ftpd.tproj/Makefile @@ -0,0 +1,53 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ftpd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = extern.h pathnames.h + +OTHERLINKED = ftpcmd.y + +CFILES = ftpd.c logwtmp.c popen.c vers.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ftpd.8 + +OTHERLINKEDOFILES = ftpcmd.o + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ftpd.tproj/Makefile.postamble b/ftpd.tproj/Makefile.postamble new file mode 100644 index 0000000..7ede358 --- /dev/null +++ b/ftpd.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/ftpd.tproj/Makefile.preamble b/ftpd.tproj/Makefile.preamble new file mode 100644 index 0000000..dcbd1c8 --- /dev/null +++ b/ftpd.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +-include ../Makefile.include diff --git a/ftpd.tproj/PB.project b/ftpd.tproj/PB.project new file mode 100644 index 0000000..b135f93 --- /dev/null +++ b/ftpd.tproj/PB.project @@ -0,0 +1,40 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (extern.h, pathnames.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (ftpcmd.y, ftpd.c, logwtmp.c, popen.c, vers.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ftpd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ftpd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ftpd.tproj/extern.h b/ftpd.tproj/extern.h new file mode 100644 index 0000000..1d02d54 --- /dev/null +++ b/ftpd.tproj/extern.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.2 (Berkeley) 4/4/94 + */ + +void blkfree __P((char **)); +char **copyblk __P((char **)); +void cwd __P((char *)); +void delete __P((char *)); +void dologout __P((int)); +void fatal __P((char *)); +int ftpd_pclose __P((FILE *)); +FILE *ftpd_popen __P((char *, char *)); +char *getline __P((char *, int, FILE *)); +void logwtmp __P((char *, char *, char *)); +void lreply __P((int, const char *, ...)); +void makedir __P((char *)); +void nack __P((char *)); +void pass __P((char *)); +void passive __P((void)); +void perror_reply __P((int, char *)); +void pwd __P((void)); +void removedir __P((char *)); +void renamecmd __P((char *, char *)); +char *renamefrom __P((char *)); +void reply __P((int, const char *, ...)); +void retrieve __P((char *, char *)); +void send_file_list __P((char *)); +void setproctitle __P((const char *, ...)); +void statcmd __P((void)); +void statfilecmd __P((char *)); +void store __P((char *, char *, int)); +void upper __P((char *)); +void user __P((char *)); +void yyerror __P((char *)); diff --git a/ftpd.tproj/ftpcmd.y b/ftpd.tproj/ftpcmd.y new file mode 100644 index 0000000..aeb59bd --- /dev/null +++ b/ftpd.tproj/ftpcmd.y @@ -0,0 +1,1269 @@ +/* + * Copyright (c) 1985, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ftpcmd.y 8.3 (Berkeley) 4/6/94 + */ + +/* + * Grammar for FTP commands. + * See RFC 959. + */ + +%{ + +#ifndef lint +static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +extern struct sockaddr_in data_dest; +extern int logged_in; +extern struct passwd *pw; +extern int guest; +extern int logging; +extern int type; +extern int form; +extern int debug; +extern int timeout; +extern int maxtimeout; +extern int pdata; +extern char hostname[], remotehost[]; +extern char proctitle[]; +extern int usedefault; +extern int transflag; +extern char tmpline[]; + +off_t restart_point; + +static int cmd_type; +static int cmd_form; +static int cmd_bytesz; +char cbuf[512]; +char *fromname; + +%} + +%union { + int i; + char *s; +} + +%token + A B C E F I + L N P R S T + + SP CRLF COMMA + + USER PASS ACCT REIN QUIT PORT + PASV TYPE STRU MODE RETR STOR + APPE MLFL MAIL MSND MSOM MSAM + MRSQ MRCP ALLO REST RNFR RNTO + ABOR DELE CWD LIST NLST SITE + STAT HELP NOOP MKD RMD PWD + CDUP STOU SMNT SYST SIZE MDTM + + UMASK IDLE CHMOD + + LEXERR + +%token STRING +%token NUMBER + +%type check_login octal_number byte_size +%type struct_code mode_code type_code form_code +%type pathstring pathname password username + +%start cmd_list + +%% + +cmd_list + : /* empty */ + | cmd_list cmd + { + fromname = (char *) 0; + restart_point = (off_t) 0; + } + | cmd_list rcmd + ; + +cmd + : USER SP username CRLF + { + user($3); + free($3); + } + | PASS SP password CRLF + { + pass($3); + free($3); + } + | PORT SP host_port CRLF + { + usedefault = 0; + if (pdata >= 0) { + (void) close(pdata); + pdata = -1; + } + reply(200, "PORT command successful."); + } + | PASV CRLF + { + passive(); + } + | TYPE SP type_code CRLF + { + switch (cmd_type) { + + case TYPE_A: + if (cmd_form == FORM_N) { + reply(200, "Type set to A."); + type = cmd_type; + form = cmd_form; + } else + reply(504, "Form must be N."); + break; + + case TYPE_E: + reply(504, "Type E not implemented."); + break; + + case TYPE_I: + reply(200, "Type set to I."); + type = cmd_type; + break; + + case TYPE_L: +#if NBBY == 8 + if (cmd_bytesz == 8) { + reply(200, + "Type set to L (byte size 8)."); + type = cmd_type; + } else + reply(504, "Byte size must be 8."); +#else /* NBBY == 8 */ + UNIMPLEMENTED for NBBY != 8 +#endif /* NBBY == 8 */ + } + } + | STRU SP struct_code CRLF + { + switch ($3) { + + case STRU_F: + reply(200, "STRU F ok."); + break; + + default: + reply(504, "Unimplemented STRU type."); + } + } + | MODE SP mode_code CRLF + { + switch ($3) { + + case MODE_S: + reply(200, "MODE S ok."); + break; + + default: + reply(502, "Unimplemented MODE type."); + } + } + | ALLO SP NUMBER CRLF + { + reply(202, "ALLO command ignored."); + } + | ALLO SP NUMBER SP R SP NUMBER CRLF + { + reply(202, "ALLO command ignored."); + } + | RETR check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + retrieve((char *) 0, $4); + if ($4 != NULL) + free($4); + } + | STOR check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + store($4, "w", 0); + if ($4 != NULL) + free($4); + } + | APPE check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + store($4, "a", 0); + if ($4 != NULL) + free($4); + } + | NLST check_login CRLF + { + if ($2) + send_file_list("."); + } + | NLST check_login SP STRING CRLF + { + if ($2 && $4 != NULL) + send_file_list($4); + if ($4 != NULL) + free($4); + } + | LIST check_login CRLF + { + if ($2) + retrieve("/bin/ls -lgA", ""); + } + | LIST check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + retrieve("/bin/ls -lgA %s", $4); + if ($4 != NULL) + free($4); + } + | STAT check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + statfilecmd($4); + if ($4 != NULL) + free($4); + } + | STAT CRLF + { + statcmd(); + } + | DELE check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + delete($4); + if ($4 != NULL) + free($4); + } + | RNTO SP pathname CRLF + { + if (fromname) { + renamecmd(fromname, $3); + free(fromname); + fromname = (char *) 0; + } else { + reply(503, "Bad sequence of commands."); + } + free($3); + } + | ABOR CRLF + { + reply(225, "ABOR command successful."); + } + | CWD check_login CRLF + { + if ($2) + cwd(pw->pw_dir); + } + | CWD check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + cwd($4); + if ($4 != NULL) + free($4); + } + | HELP CRLF + { + help(cmdtab, (char *) 0); + } + | HELP SP STRING CRLF + { + char *cp = $3; + + if (strncasecmp(cp, "SITE", 4) == 0) { + cp = $3 + 4; + if (*cp == ' ') + cp++; + if (*cp) + help(sitetab, cp); + else + help(sitetab, (char *) 0); + } else + help(cmdtab, $3); + } + | NOOP CRLF + { + reply(200, "NOOP command successful."); + } + | MKD check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + makedir($4); + if ($4 != NULL) + free($4); + } + | RMD check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + removedir($4); + if ($4 != NULL) + free($4); + } + | PWD check_login CRLF + { + if ($2) + pwd(); + } + | CDUP check_login CRLF + { + if ($2) + cwd(".."); + } + | SITE SP HELP CRLF + { + help(sitetab, (char *) 0); + } + | SITE SP HELP SP STRING CRLF + { + help(sitetab, $5); + } + | SITE SP UMASK check_login CRLF + { + int oldmask; + + if ($4) { + oldmask = umask(0); + (void) umask(oldmask); + reply(200, "Current UMASK is %03o", oldmask); + } + } + | SITE SP UMASK check_login SP octal_number CRLF + { + int oldmask; + + if ($4) { + if (($6 == -1) || ($6 > 0777)) { + reply(501, "Bad UMASK value"); + } else { + oldmask = umask($6); + reply(200, + "UMASK set to %03o (was %03o)", + $6, oldmask); + } + } + } + | SITE SP CHMOD check_login SP octal_number SP pathname CRLF + { + if ($4 && ($8 != NULL)) { + if ($6 > 0777) + reply(501, + "CHMOD: Mode value must be between 0 and 0777"); + else if (chmod($8, $6) < 0) + perror_reply(550, $8); + else + reply(200, "CHMOD command successful."); + } + if ($8 != NULL) + free($8); + } + | SITE SP IDLE CRLF + { + reply(200, + "Current IDLE time limit is %d seconds; max %d", + timeout, maxtimeout); + } + | SITE SP IDLE SP NUMBER CRLF + { + if ($5 < 30 || $5 > maxtimeout) { + reply(501, + "Maximum IDLE time must be between 30 and %d seconds", + maxtimeout); + } else { + timeout = $5; + (void) alarm((unsigned) timeout); + reply(200, + "Maximum IDLE time set to %d seconds", + timeout); + } + } + | STOU check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + store($4, "w", 1); + if ($4 != NULL) + free($4); + } + | SYST CRLF + { +#ifdef __APPLE__ + reply(215, "BSD Type: L%d", NBBY); +#else +#if defined(unix) +#ifdef BSD + reply(215, "UNIX Type: L%d Version: BSD-%d", NBBY, BSD); +#else /* BSD */ + reply(215, "UNIX Type: L%d", NBBY); +#endif /* BSD */ +#else /* unix */ + reply(215, "UNKNOWN Type: L%d", NBBY); +#endif /* unix */ +#endif /* __APPLE__ */ + } + + /* + * SIZE is not in RFC959, but Postel has blessed it and + * it will be in the updated RFC. + * + * Return size of file in a format suitable for + * using with RESTART (we just count bytes). + */ + | SIZE check_login SP pathname CRLF + { + if ($2 && $4 != NULL) + sizecmd($4); + if ($4 != NULL) + free($4); + } + + /* + * MDTM is not in RFC959, but Postel has blessed it and + * it will be in the updated RFC. + * + * Return modification time of file as an ISO 3307 + * style time. E.g. YYYYMMDDHHMMSS or YYYYMMDDHHMMSS.xxx + * where xxx is the fractional second (of any precision, + * not necessarily 3 digits) + */ + | MDTM check_login SP pathname CRLF + { + if ($2 && $4 != NULL) { + struct stat stbuf; + if (stat($4, &stbuf) < 0) + reply(550, "%s: %s", + $4, strerror(errno)); + else if (!S_ISREG(stbuf.st_mode)) { + reply(550, "%s: not a plain file.", $4); + } else { + struct tm *t; + t = gmtime(&stbuf.st_mtime); + reply(213, + "%04d%02d%02d%02d%02d%02d", + 1900+t->tm_year, t->tm_mon+1, t->tm_mday, + t->tm_hour, t->tm_min, t->tm_sec); + } + } + if ($4 != NULL) + free($4); + } + | QUIT CRLF + { + reply(221, "Goodbye."); + dologout(0); + } + | error CRLF + { + yyerrok; + } + ; +rcmd + : RNFR check_login SP pathname CRLF + { + char *renamefrom(); + + restart_point = (off_t) 0; + if ($2 && $4) { + fromname = renamefrom($4); + if (fromname == (char *) 0 && $4) { + free($4); + } + } + } + | REST SP byte_size CRLF + { + fromname = (char *) 0; + restart_point = $3; /* XXX $3 is only "int" */ + reply(350, "Restarting at %qd. %s", restart_point, + "Send STORE or RETRIEVE to initiate transfer."); + } + ; + +username + : STRING + ; + +password + : /* empty */ + { + $$ = (char *)calloc(1, sizeof(char)); + } + | STRING + ; + +byte_size + : NUMBER + ; + +host_port + : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA + NUMBER COMMA NUMBER + { + char *a, *p; + + a = (char *)&data_dest.sin_addr; + a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; + p = (char *)&data_dest.sin_port; + p[0] = $9; p[1] = $11; + data_dest.sin_family = AF_INET; + } + ; + +form_code + : N + { + $$ = FORM_N; + } + | T + { + $$ = FORM_T; + } + | C + { + $$ = FORM_C; + } + ; + +type_code + : A + { + cmd_type = TYPE_A; + cmd_form = FORM_N; + } + | A SP form_code + { + cmd_type = TYPE_A; + cmd_form = $3; + } + | E + { + cmd_type = TYPE_E; + cmd_form = FORM_N; + } + | E SP form_code + { + cmd_type = TYPE_E; + cmd_form = $3; + } + | I + { + cmd_type = TYPE_I; + } + | L + { + cmd_type = TYPE_L; + cmd_bytesz = NBBY; + } + | L SP byte_size + { + cmd_type = TYPE_L; + cmd_bytesz = $3; + } + /* this is for a bug in the BBN ftp */ + | L byte_size + { + cmd_type = TYPE_L; + cmd_bytesz = $2; + } + ; + +struct_code + : F + { + $$ = STRU_F; + } + | R + { + $$ = STRU_R; + } + | P + { + $$ = STRU_P; + } + ; + +mode_code + : S + { + $$ = MODE_S; + } + | B + { + $$ = MODE_B; + } + | C + { + $$ = MODE_C; + } + ; + +pathname + : pathstring + { + /* + * Problem: this production is used for all pathname + * processing, but only gives a 550 error reply. + * This is a valid reply in some cases but not in others. + */ + if (logged_in && $1 && *$1 == '~') { + glob_t gl; + int flags = + GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (glob($1, flags, NULL, &gl) || + gl.gl_pathc == 0) { + reply(550, "not found"); + $$ = NULL; + } else { + $$ = strdup(gl.gl_pathv[0]); + } + globfree(&gl); + free($1); + } else + $$ = $1; + } + ; + +pathstring + : STRING + ; + +octal_number + : NUMBER + { + int ret, dec, multby, digit; + + /* + * Convert a number that was read as decimal number + * to what it would be if it had been read as octal. + */ + dec = $1; + multby = 1; + ret = 0; + while (dec) { + digit = dec%10; + if (digit > 7) { + ret = -1; + break; + } + ret += digit * multby; + multby *= 8; + dec /= 10; + } + $$ = ret; + } + ; + + +check_login + : /* empty */ + { + if (logged_in) + $$ = 1; + else { + reply(530, "Please login with USER and PASS."); + $$ = 0; + } + } + ; + +%% + +extern jmp_buf errcatch; + +#define CMD 0 /* beginning of command */ +#define ARGS 1 /* expect miscellaneous arguments */ +#define STR1 2 /* expect SP followed by STRING */ +#define STR2 3 /* expect STRING */ +#define OSTR 4 /* optional SP then STRING */ +#define ZSTR1 5 /* SP then optional STRING */ +#define ZSTR2 6 /* optional STRING after SP */ +#define SITECMD 7 /* SITE command */ +#define NSTR 8 /* Number followed by a string */ + +struct tab { + char *name; + short token; + short state; + short implemented; /* 1 if command is implemented */ + char *help; +}; + +struct tab cmdtab[] = { /* In order defined in RFC 765 */ + { "USER", USER, STR1, 1, " username" }, + { "PASS", PASS, ZSTR1, 1, " password" }, + { "ACCT", ACCT, STR1, 0, "(specify account)" }, + { "SMNT", SMNT, ARGS, 0, "(structure mount)" }, + { "REIN", REIN, ARGS, 0, "(reinitialize server state)" }, + { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, + { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4" }, + { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, + { "TYPE", TYPE, ARGS, 1, " [ A | E | I | L ]" }, + { "STRU", STRU, ARGS, 1, "(specify file structure)" }, + { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, + { "RETR", RETR, STR1, 1, " file-name" }, + { "STOR", STOR, STR1, 1, " file-name" }, + { "APPE", APPE, STR1, 1, " file-name" }, + { "MLFL", MLFL, OSTR, 0, "(mail file)" }, + { "MAIL", MAIL, OSTR, 0, "(mail to user)" }, + { "MSND", MSND, OSTR, 0, "(mail send to terminal)" }, + { "MSOM", MSOM, OSTR, 0, "(mail send to terminal or mailbox)" }, + { "MSAM", MSAM, OSTR, 0, "(mail send to terminal and mailbox)" }, + { "MRSQ", MRSQ, OSTR, 0, "(mail recipient scheme question)" }, + { "MRCP", MRCP, STR1, 0, "(mail recipient)" }, + { "ALLO", ALLO, ARGS, 1, "allocate storage (vacuously)" }, + { "REST", REST, ARGS, 1, " offset (restart command)" }, + { "RNFR", RNFR, STR1, 1, " file-name" }, + { "RNTO", RNTO, STR1, 1, " file-name" }, + { "ABOR", ABOR, ARGS, 1, "(abort operation)" }, + { "DELE", DELE, STR1, 1, " file-name" }, + { "CWD", CWD, OSTR, 1, "[ directory-name ]" }, + { "XCWD", CWD, OSTR, 1, "[ directory-name ]" }, + { "LIST", LIST, OSTR, 1, "[ path-name ]" }, + { "NLST", NLST, OSTR, 1, "[ path-name ]" }, + { "SITE", SITE, SITECMD, 1, "site-cmd [ arguments ]" }, + { "SYST", SYST, ARGS, 1, "(get type of operating system)" }, + { "STAT", STAT, OSTR, 1, "[ path-name ]" }, + { "HELP", HELP, OSTR, 1, "[ ]" }, + { "NOOP", NOOP, ARGS, 1, "" }, + { "MKD", MKD, STR1, 1, " path-name" }, + { "XMKD", MKD, STR1, 1, " path-name" }, + { "RMD", RMD, STR1, 1, " path-name" }, + { "XRMD", RMD, STR1, 1, " path-name" }, + { "PWD", PWD, ARGS, 1, "(return current directory)" }, + { "XPWD", PWD, ARGS, 1, "(return current directory)" }, + { "CDUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "XCUP", CDUP, ARGS, 1, "(change to parent directory)" }, + { "STOU", STOU, STR1, 1, " file-name" }, + { "SIZE", SIZE, OSTR, 1, " path-name" }, + { "MDTM", MDTM, OSTR, 1, " path-name" }, + { NULL, 0, 0, 0, 0 } +}; + +struct tab sitetab[] = { + { "UMASK", UMASK, ARGS, 1, "[ umask ]" }, + { "IDLE", IDLE, ARGS, 1, "[ maximum-idle-time ]" }, + { "CHMOD", CHMOD, NSTR, 1, " mode file-name" }, + { "HELP", HELP, OSTR, 1, "[ ]" }, + { NULL, 0, 0, 0, 0 } +}; + +static char *copy __P((char *)); +static void help __P((struct tab *, char *)); +static struct tab * + lookup __P((struct tab *, char *)); +static void sizecmd __P((char *)); +static void toolong __P((int)); +static int yylex __P((void)); + +static struct tab * +lookup(p, cmd) + struct tab *p; + char *cmd; +{ + + for (; p->name != NULL; p++) + if (strcmp(cmd, p->name) == 0) + return (p); + return (0); +} + +#include + +/* + * getline - a hacked up version of fgets to ignore TELNET escape codes. + */ +char * +getline(s, n, iop) + char *s; + int n; + FILE *iop; +{ + int c; + register char *cs; + + cs = s; +/* tmpline may contain saved command from urgent mode interruption */ + for (c = 0; tmpline[c] != '\0' && --n > 0; ++c) { + *cs++ = tmpline[c]; + if (tmpline[c] == '\n') { + *cs++ = '\0'; + if (debug) + syslog(LOG_DEBUG, "command: %s", s); + tmpline[0] = '\0'; + return(s); + } + if (c == 0) + tmpline[0] = '\0'; + } + while ((c = getc(iop)) != EOF) { + c &= 0377; + if (c == IAC) { + if ((c = getc(iop)) != EOF) { + c &= 0377; + switch (c) { + case WILL: + case WONT: + c = getc(iop); + printf("%c%c%c", IAC, DONT, 0377&c); + (void) fflush(stdout); + continue; + case DO: + case DONT: + c = getc(iop); + printf("%c%c%c", IAC, WONT, 0377&c); + (void) fflush(stdout); + continue; + case IAC: + break; + default: + continue; /* ignore command */ + } + } + } + *cs++ = c; + if (--n <= 0 || c == '\n') + break; + } + if (c == EOF && cs == s) + return (NULL); + *cs++ = '\0'; + if (debug) { + if (!guest && strncasecmp("pass ", s, 5) == 0) { + /* Don't syslog passwords */ + syslog(LOG_DEBUG, "command: %.5s ???", s); + } else { + register char *cp; + register int len; + + /* Don't syslog trailing CR-LF */ + len = strlen(s); + cp = s + len - 1; + while (cp >= s && (*cp == '\n' || *cp == '\r')) { + --cp; + --len; + } + syslog(LOG_DEBUG, "command: %.*s", len, s); + } + } + return (s); +} + +static void +toolong(signo) + int signo; +{ + + reply(421, + "Timeout (%d seconds): closing control connection.", timeout); + if (logging) + syslog(LOG_INFO, "User %s timed out after %d seconds", + (pw ? pw -> pw_name : "unknown"), timeout); + dologout(1); +} + +static int +yylex() +{ + static int cpos, state; + char *cp, *cp2; + struct tab *p; + int n; + char c; + + for (;;) { + switch (state) { + + case CMD: + (void) signal(SIGALRM, toolong); + (void) alarm((unsigned) timeout); + if (getline(cbuf, sizeof(cbuf)-1, stdin) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + (void) alarm(0); +#ifdef SETPROCTITLE + if (strncasecmp(cbuf, "PASS", 4) != NULL) + setproctitle("%s: %s", proctitle, cbuf); +#endif /* SETPROCTITLE */ + if ((cp = strchr(cbuf, '\r'))) { + *cp++ = '\n'; + *cp = '\0'; + } + if ((cp = strpbrk(cbuf, " \n"))) + cpos = cp - cbuf; + if (cpos == 0) + cpos = 4; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + upper(cbuf); + p = lookup(cmdtab, cbuf); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + nack(p->name); + longjmp(errcatch,0); + /* NOTREACHED */ + } + state = p->state; + yylval.s = p->name; + return (p->token); + } + break; + + case SITECMD: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + cp = &cbuf[cpos]; + if ((cp2 = strpbrk(cp, " \n"))) + cpos = cp2 - cbuf; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + upper(cp); + p = lookup(sitetab, cp); + cbuf[cpos] = c; + if (p != 0) { + if (p->implemented == 0) { + state = CMD; + nack(p->name); + longjmp(errcatch,0); + /* NOTREACHED */ + } + state = p->state; + yylval.s = p->name; + return (p->token); + } + state = CMD; + break; + + case OSTR: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR1: + case ZSTR1: + dostr1: + if (cbuf[cpos] == ' ') { + cpos++; + state = state == OSTR ? STR2 : ++state; + return (SP); + } + break; + + case ZSTR2: + if (cbuf[cpos] == '\n') { + state = CMD; + return (CRLF); + } + /* FALLTHROUGH */ + + case STR2: + cp = &cbuf[cpos]; + n = strlen(cp); + cpos += n - 1; + /* + * Make sure the string is nonempty and \n terminated. + */ + if (n > 1 && cbuf[cpos] == '\n') { + cbuf[cpos] = '\0'; + yylval.s = copy(cp); + cbuf[cpos] = '\n'; + state = ARGS; + return (STRING); + } + break; + + case NSTR: + if (cbuf[cpos] == ' ') { + cpos++; + return (SP); + } + if (isdigit(cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit(cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval.i = atoi(cp); + cbuf[cpos] = c; + state = STR1; + return (NUMBER); + } + state = STR1; + goto dostr1; + + case ARGS: + if (isdigit(cbuf[cpos])) { + cp = &cbuf[cpos]; + while (isdigit(cbuf[++cpos])) + ; + c = cbuf[cpos]; + cbuf[cpos] = '\0'; + yylval.i = atoi(cp); + cbuf[cpos] = c; + return (NUMBER); + } + switch (cbuf[cpos++]) { + + case '\n': + state = CMD; + return (CRLF); + + case ' ': + return (SP); + + case ',': + return (COMMA); + + case 'A': + case 'a': + return (A); + + case 'B': + case 'b': + return (B); + + case 'C': + case 'c': + return (C); + + case 'E': + case 'e': + return (E); + + case 'F': + case 'f': + return (F); + + case 'I': + case 'i': + return (I); + + case 'L': + case 'l': + return (L); + + case 'N': + case 'n': + return (N); + + case 'P': + case 'p': + return (P); + + case 'R': + case 'r': + return (R); + + case 'S': + case 's': + return (S); + + case 'T': + case 't': + return (T); + + } + break; + + default: + fatal("Unknown state in scanner."); + } + yyerror((char *) 0); + state = CMD; + longjmp(errcatch,0); + } +} + +void +upper(s) + char *s; +{ + while (*s != '\0') { + if (islower(*s)) + *s = toupper(*s); + s++; + } +} + +static char * +copy(s) + char *s; +{ + char *p; + + p = malloc((unsigned) strlen(s) + 1); + if (p == NULL) + fatal("Ran out of memory."); + (void) strcpy(p, s); + return (p); +} + +static void +help(ctab, s) + struct tab *ctab; + char *s; +{ + struct tab *c; + int width, NCMDS; + char *type; + + if (ctab == sitetab) + type = "SITE "; + else + type = ""; + width = 0, NCMDS = 0; + for (c = ctab; c->name != NULL; c++) { + int len = strlen(c->name); + + if (len > width) + width = len; + NCMDS++; + } + width = (width + 8) &~ 7; + if (s == 0) { + int i, j, w; + int columns, lines; + + lreply(214, "The following %scommands are recognized %s.", + type, "(* =>'s unimplemented)"); + columns = 76 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + printf(" "); + for (j = 0; j < columns; j++) { + c = ctab + j * lines + i; + printf("%s%c", c->name, + c->implemented ? ' ' : '*'); + if (c + lines >= &ctab[NCMDS]) + break; + w = strlen(c->name) + 1; + while (w < width) { + putchar(' '); + w++; + } + } + printf("\r\n"); + } + (void) fflush(stdout); + reply(214, "Direct comments to ftp-bugs@%s.", hostname); + return; + } + upper(s); + c = lookup(ctab, s); + if (c == (struct tab *)0) { + reply(502, "Unknown command %s.", s); + return; + } + if (c->implemented) + reply(214, "Syntax: %s%s %s", type, c->name, c->help); + else + reply(214, "%s%-*s\t%s; unimplemented.", type, width, + c->name, c->help); +} + +static void +sizecmd(filename) + char *filename; +{ + switch (type) { + case TYPE_L: + case TYPE_I: { + struct stat stbuf; + if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) + reply(550, "%s: not a plain file.", filename); + else + reply(213, "%qu", stbuf.st_size); + break; } + case TYPE_A: { + FILE *fin; + int c; + off_t count; + struct stat stbuf; + fin = fopen(filename, "r"); + if (fin == NULL) { + perror_reply(550, filename); + return; + } + if (fstat(fileno(fin), &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) { + reply(550, "%s: not a plain file.", filename); + (void) fclose(fin); + return; + } + + count = 0; + while((c=getc(fin)) != EOF) { + if (c == '\n') /* will get expanded to \r\n */ + count++; + count++; + } + (void) fclose(fin); + + reply(213, "%qd", count); + break; } + default: + reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); + } +} diff --git a/ftpd.tproj/ftpd.8 b/ftpd.tproj/ftpd.8 new file mode 100644 index 0000000..eb93c38 --- /dev/null +++ b/ftpd.tproj/ftpd.8 @@ -0,0 +1,291 @@ +.\" Copyright (c) 1985, 1988, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ftpd.8 8.3 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt FTPD 8 +.Os BSD 4.2 +.Sh NAME +.Nm ftpd +.Nd +Internet File Transfer Protocol server +.Sh SYNOPSIS +.Nm ftpd +.Op Fl dl +.Op Fl T Ar maxtimeout +.Op Fl t Ar timeout +.Sh DESCRIPTION +.Nm Ftpd +is the +Internet File Transfer Protocol +server process. The server uses the +.Tn TCP +protocol +and listens at the port specified in the +.Dq ftp +service specification; see +.Xr services 5 . +.Pp +Available options: +.Bl -tag -width Ds +.It Fl d +Debugging information is written to the syslog using LOG_FTP. +.It Fl l +Each successful and failed +.Xr ftp 1 +session is logged using syslog with a facility of LOG_FTP. +If this option is specified twice, the retrieve (get), store (put), append, +delete, make directory, remove directory and rename operations and +their filename arguments are also logged. +.It Fl T +A client may also request a different timeout period; +the maximum period allowed may be set to +.Ar timeout +seconds with the +.Fl T +option. +The default limit is 2 hours. +.It Fl t +The inactivity timeout period is set to +.Ar timeout +seconds (the default is 15 minutes). +.El +.Pp +The file +.Pa /etc/nologin +can be used to disable ftp access. +If the file exists, +.Nm +displays it and exits. +If the file +.Pa /etc/ftpwelcome +exists, +.Nm +prints it before issuing the +.Dq ready +message. +If the file +.Pa /etc/motd +exists, +.Nm +prints it after a successful login. +.Pp +The ftp server currently supports the following ftp requests. +The case of the requests is ignored. +.Bl -column "Request" -offset indent +.It Request Ta "Description" +.It ABOR Ta "abort previous command" +.It ACCT Ta "specify account (ignored)" +.It ALLO Ta "allocate storage (vacuously)" +.It APPE Ta "append to a file" +.It CDUP Ta "change to parent of current working directory" +.It CWD Ta "change working directory" +.It DELE Ta "delete a file" +.It HELP Ta "give help information" +.It LIST Ta "give list files in a directory" Pq Dq Li "ls -lgA" +.It MKD Ta "make a directory" +.It MDTM Ta "show last modification time of file" +.It MODE Ta "specify data transfer" Em mode +.It NLST Ta "give name list of files in directory" +.It NOOP Ta "do nothing" +.It PASS Ta "specify password" +.It PASV Ta "prepare for server-to-server transfer" +.It PORT Ta "specify data connection port" +.It PWD Ta "print the current working directory" +.It QUIT Ta "terminate session" +.It REST Ta "restart incomplete transfer" +.It RETR Ta "retrieve a file" +.It RMD Ta "remove a directory" +.It RNFR Ta "specify rename-from file name" +.It RNTO Ta "specify rename-to file name" +.It SITE Ta "non-standard commands (see next section)" +.It SIZE Ta "return size of file" +.It STAT Ta "return status of server" +.It STOR Ta "store a file" +.It STOU Ta "store a file with a unique name" +.It STRU Ta "specify data transfer" Em structure +.It SYST Ta "show operating system type of server system" +.It TYPE Ta "specify data transfer" Em type +.It USER Ta "specify user name" +.It XCUP Ta "change to parent of current working directory (deprecated)" +.It XCWD Ta "change working directory (deprecated)" +.It XMKD Ta "make a directory (deprecated)" +.It XPWD Ta "print the current working directory (deprecated)" +.It XRMD Ta "remove a directory (deprecated)" +.El +.Pp +The following non-standard or +.Tn UNIX +specific commands are supported +by the +SITE request. +.Pp +.Bl -column Request -offset indent +.It Sy Request Ta Sy Description +.It UMASK Ta change umask, e.g. ``SITE UMASK 002'' +.It IDLE Ta set idle-timer, e.g. ``SITE IDLE 60'' +.It CHMOD Ta change mode of a file, e.g. ``SITE CHMOD 755 filename'' +.It HELP Ta give help information. +.El +.Pp +The remaining ftp requests specified in Internet RFC 959 +are +recognized, but not implemented. +MDTM and SIZE are not specified in RFC 959, but will appear in the +next updated FTP RFC. +.Pp +The ftp server will abort an active file transfer only when the +ABOR +command is preceded by a Telnet "Interrupt Process" (IP) +signal and a Telnet "Synch" signal in the command Telnet stream, +as described in Internet RFC 959. +If a +STAT +command is received during a data transfer, preceded by a Telnet IP +and Synch, transfer status will be returned. +.Pp +.Nm Ftpd +interprets file names according to the +.Dq globbing +conventions used by +.Xr csh 1 . +This allows users to utilize the metacharacters +.Dq Li \&*?[]{}~ . +.Pp +.Nm Ftpd +authenticates users according to three rules. +.Pp +.Bl -enum -offset indent +.It +The login name must be in the password data base, +.Pa /etc/passwd , +and not have a null password. +In this case a password must be provided by the client before any +file operations may be performed. +.It +The login name must not appear in the file +.Pa /etc/ftpusers . +.It +The user must have a standard shell returned by +.Xr getusershell 3 . +.It +If the user name is +.Dq anonymous +or +.Dq ftp , +an +anonymous ftp account must be present in the password +file (user +.Dq ftp ) . +In this case the user is allowed +to log in by specifying any password (by convention an email address for +the user should be used as the password). +.El +.Pp +In the last case, +.Nm ftpd +takes special measures to restrict the client's access privileges. +The server performs a +.Xr chroot 2 +to the home directory of the +.Dq ftp +user. +In order that system security is not breached, it is recommended +that the +.Dq ftp +subtree be constructed with care, following these rules: +.Bl -tag -width "~ftp/pub" -offset indent +.It Pa ~ftp +Make the home directory owned by +.Dq root +and unwritable by anyone. +.ne 1i +.It Pa ~ftp/bin +Make this directory owned by +.Dq root +and unwritable by anyone (mode 555). +The program +.Xr ls 1 +must be present to support the list command. +This program should be mode 111. +.It Pa ~ftp/etc +Make this directory owned by +.Dq root +and unwritable by anyone (mode 555). +The files +.Xr passwd 5 +and +.Xr group 5 +must be present for the +.Xr ls +command to be able to produce owner names rather than numbers. +The password field in +.Xr passwd +is not used, and should not contain real passwords. +The file +.Pa motd , +if present, will be printed after a successful login. +These files should be mode 444. +.It Pa ~ftp/pub +Make this directory mode 777 and owned by +.Dq ftp . +Guests +can then place files which are to be accessible via the anonymous +account in this directory. +.El +.Sh FILES +.Bl -tag -width /etc/ftpwelcome -compact +.It Pa /etc/ftpusers +List of unwelcome/restricted users. +.It Pa /etc/ftpwelcome +Welcome notice. +.It Pa /etc/motd +Welcome notice after login. +.It Pa /etc/nologin +Displayed and access refused. +.El +.Sh SEE ALSO +.Xr ftp 1 , +.Xr getusershell 3 , +.Xr syslogd 8 +.Sh BUGS +The server must run as the super-user +to create sockets with privileged port numbers. It maintains +an effective user id of the logged in user, reverting to +the super-user only when binding addresses to sockets. The +possible security holes have been extensively +scrutinized, but are possibly incomplete. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/ftpd.tproj/ftpd.c b/ftpd.tproj/ftpd.c new file mode 100644 index 0000000..4071f02 --- /dev/null +++ b/ftpd.tproj/ftpd.c @@ -0,0 +1,1686 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ftpd.c 8.5 (Berkeley) 4/28/95"; +#endif /* not lint */ + +/* XXX this is to get around a compiler bug with long long's on ppc */ +#pragma CC_OPT_OFF + +/* + * FTP server. + */ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define FTP_NAMES +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pathnames.h" +#include "extern.h" + +#if __STDC__ +#include +#else +#include +#endif + +static char version[] = "Version 6.00"; + +extern off_t restart_point; +extern char cbuf[]; + +struct sockaddr_in ctrl_addr; +struct sockaddr_in data_source; +struct sockaddr_in data_dest; +struct sockaddr_in his_addr; +struct sockaddr_in pasv_addr; + +int data; +jmp_buf errcatch, urgcatch; +int logged_in; +struct passwd *pw; +int debug; +int timeout = 900; /* timeout after 15 minutes of inactivity */ +int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ +int logging; +int guest; +int type; +int form; +int stru; /* avoid C keyword */ +int mode; +int usedefault = 1; /* for data transfers */ +int pdata = -1; /* for passive mode */ +sig_atomic_t transflag; +off_t file_size; +off_t byte_count; +#if !defined(CMASK) || CMASK == 0 +#undef CMASK +#define CMASK 027 +#endif +int defumask = CMASK; /* default umask value */ +char tmpline[7]; +char hostname[MAXHOSTNAMELEN]; +char remotehost[MAXHOSTNAMELEN]; + +/* + * Timeout intervals for retrying connections + * to hosts that don't accept PORT cmds. This + * is a kludge, but given the problems with TCP... + */ +#define SWAITMAX 90 /* wait at most 90 seconds */ +#define SWAITINT 5 /* interval between retries */ + +int swaitmax = SWAITMAX; +int swaitint = SWAITINT; + +#ifdef SETPROCTITLE +char **Argv = NULL; /* pointer to argument vector */ +char *LastArgv = NULL; /* end of argv */ +char proctitle[LINE_MAX]; /* initial part of title */ +#endif /* SETPROCTITLE */ + +#define LOGCMD(cmd, file) \ + if (logging > 1) \ + syslog(LOG_INFO,"%s %s%s", cmd, \ + *(file) == '/' ? "" : curdir(), file); +#define LOGCMD2(cmd, file1, file2) \ + if (logging > 1) \ + syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ + *(file1) == '/' ? "" : curdir(), file1, \ + *(file2) == '/' ? "" : curdir(), file2); +#define LOGBYTES(cmd, file, cnt) \ + if (logging > 1) { \ + if (cnt == (off_t)-1) \ + syslog(LOG_INFO,"%s %s%s", cmd, \ + *(file) == '/' ? "" : curdir(), file); \ + else \ + syslog(LOG_INFO, "%s %s%s = %qd bytes", \ + cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \ + } + +static void ack __P((char *)); +static void myoob __P((int)); +static int checkuser __P((char *)); +static FILE *dataconn __P((char *, off_t, char *)); +static void dolog __P((struct sockaddr_in *)); +static char *curdir __P((void)); +static void end_login __P((void)); +static FILE *getdatasock __P((char *)); +static char *gunique __P((char *)); +static void lostconn __P((int)); +static int receive_data __P((FILE *, FILE *)); +static void send_data __P((FILE *, FILE *, off_t)); +static struct passwd * + sgetpwnam __P((char *)); +static char *sgetsave __P((char *)); + +static char * +curdir() +{ + static char path[MAXPATHLEN+1+1]; /* path + '/' + '\0' */ + + if (getcwd(path, sizeof(path)-2) == NULL) + return (""); + if (path[1] != '\0') /* special case for root dir. */ + strcat(path, "/"); + /* For guest account, skip / since it's chrooted */ + return (guest ? path+1 : path); +} + +int +main(argc, argv, envp) + int argc; + char *argv[]; + char **envp; +{ + int addrlen, ch, on = 1, tos; + char *cp, line[LINE_MAX]; + FILE *fd; + + /* + * LOG_NDELAY sets up the logging connection immediately, + * necessary for anonymous ftp's that chroot and can't do it later. + */ + openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); + addrlen = sizeof(his_addr); + if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); + exit(1); + } + addrlen = sizeof(ctrl_addr); + if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); + exit(1); + } +#ifdef IP_TOS + tos = IPTOS_LOWDELAY; + if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif + data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); + debug = 0; +#ifdef SETPROCTITLE + /* + * Save start and extent of argv for setproctitle. + */ + Argv = argv; + while (*envp) + envp++; + LastArgv = envp[-1] + strlen(envp[-1]); +#endif /* SETPROCTITLE */ + + while ((ch = getopt(argc, argv, "dlt:T:u:v")) != -1) { + switch (ch) { + case 'd': + debug = 1; + break; + + case 'l': + logging++; /* > 1 == extra logging */ + break; + + case 't': + timeout = atoi(optarg); + if (maxtimeout < timeout) + maxtimeout = timeout; + break; + + case 'T': + maxtimeout = atoi(optarg); + if (timeout > maxtimeout) + timeout = maxtimeout; + break; + + case 'u': + { + long val = 0; + + val = strtol(optarg, &optarg, 8); + if (*optarg != '\0' || val < 0) + warnx("bad value for -u"); + else + defumask = val; + break; + } + + case 'v': + debug = 1; + break; + + default: + warnx("unknown flag -%c ignored", optopt); + break; + } + } + (void) freopen(_PATH_DEVNULL, "w", stderr); + (void) signal(SIGPIPE, lostconn); + (void) signal(SIGCHLD, SIG_IGN); + if ((int)signal(SIGURG, myoob) < 0) + syslog(LOG_ERR, "signal: %m"); + + /* Try to handle urgent data inline */ +#ifdef SO_OOBINLINE + if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt: %m"); +#endif + +#ifdef F_SETOWN + if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) + syslog(LOG_ERR, "fcntl F_SETOWN: %m"); +#endif + dolog(&his_addr); + /* + * Set up default state + */ + data = -1; + type = TYPE_A; + form = FORM_N; + stru = STRU_F; + mode = MODE_S; + tmpline[0] = '\0'; + + /* If logins are disabled, print out the message. */ + if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(530, "%s", line); + } + (void) fflush(stdout); + (void) fclose(fd); + reply(530, "System not available."); + exit(0); + } + if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(220, "%s", line); + } + (void) fflush(stdout); + (void) fclose(fd); + /* reply(220,) must follow */ + } + (void) gethostname(hostname, sizeof(hostname)); + reply(220, "%s FTP server (%s) ready.", hostname, version); + (void) setjmp(errcatch); + for (;;) + (void) yyparse(); + /* NOTREACHED */ +} + +static void +lostconn(signo) + int signo; +{ + + if (debug) + syslog(LOG_DEBUG, "lost connection"); + dologout(-1); +} + +static char ttyline[20]; + +/* + * Helper function for sgetpwnam(). + */ +static char * +sgetsave(s) + char *s; +{ + char *new = malloc((unsigned) strlen(s) + 1); + + if (new == NULL) { + perror_reply(421, "Local resource failure: malloc"); + dologout(1); + /* NOTREACHED */ + } + (void) strcpy(new, s); + return (new); +} + +/* + * Save the result of a getpwnam. Used for USER command, since + * the data returned must not be clobbered by any other command + * (e.g., globbing). + */ +static struct passwd * +sgetpwnam(name) + char *name; +{ + static struct passwd save; + struct passwd *p; + + if ((p = getpwnam(name)) == NULL) + return (p); + if (save.pw_name) { + free(save.pw_name); + free(save.pw_passwd); + free(save.pw_gecos); + free(save.pw_dir); + free(save.pw_shell); + } + save = *p; + save.pw_name = sgetsave(p->pw_name); + save.pw_passwd = sgetsave(p->pw_passwd); + save.pw_gecos = sgetsave(p->pw_gecos); + save.pw_dir = sgetsave(p->pw_dir); + save.pw_shell = sgetsave(p->pw_shell); + return (&save); +} + +static int login_attempts; /* number of failed login attempts */ +static int askpasswd; /* had user command, ask for passwd */ +static char curname[10]; /* current USER name */ + +/* + * USER command. + * Sets global passwd pointer pw if named account exists and is acceptable; + * sets askpasswd if a PASS command is expected. If logged in previously, + * need to reset state. If name is "ftp" or "anonymous", the name is not in + * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return. + * If account doesn't exist, ask for passwd anyway. Otherwise, check user + * requesting login privileges. Disallow anyone who does not have a standard + * shell as returned by getusershell(). Disallow anyone mentioned in the file + * _PATH_FTPUSERS to allow people such as root and uucp to be avoided. + */ +void +user(name) + char *name; +{ + char *cp, *shell; + + if (logged_in) { + if (guest) { + reply(530, "Can't change user from guest login."); + return; + } + end_login(); + } + + guest = 0; + if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { + if (checkuser("ftp") || checkuser("anonymous")) + reply(530, "User %s access denied.", name); + else if ((pw = sgetpwnam("ftp")) != NULL) { + guest = 1; + askpasswd = 1; + reply(331, + "Guest login ok, type your name as password."); + } else + reply(530, "User %s unknown.", name); + if (!askpasswd && logging) + syslog(LOG_NOTICE, + "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); + return; + } + if (pw = sgetpwnam(name)) { + if ((shell = pw->pw_shell) == NULL || *shell == 0) + shell = _PATH_BSHELL; + while ((cp = getusershell()) != NULL) + if (strcmp(cp, shell) == 0) + break; + endusershell(); + + if (cp == NULL || checkuser(name)) { + reply(530, "User %s access denied.", name); + if (logging) + syslog(LOG_NOTICE, + "FTP LOGIN REFUSED FROM %s, %s", + remotehost, name); + pw = (struct passwd *) NULL; + return; + } + } + if (logging) + strncpy(curname, name, sizeof(curname)-1); + reply(331, "Password required for %s.", name); + askpasswd = 1; + /* + * Delay before reading passwd after first failed + * attempt to slow down passwd-guessing programs. + */ + if (login_attempts) + sleep((unsigned) login_attempts); +} + +/* + * Check if a user is in the file _PATH_FTPUSERS + */ +static int +checkuser(name) + char *name; +{ + FILE *fd; + int found = 0; + char *p, line[BUFSIZ]; + + if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) + if ((p = strchr(line, '\n')) != NULL) { + *p = '\0'; + if (line[0] == '#') + continue; + if (strcmp(line, name) == 0) { + found = 1; + break; + } + } + (void) fclose(fd); + } + return (found); +} + +/* + * Terminate login as previous user, if any, resetting state; + * used when USER command is given or login fails. + */ +static void +end_login() +{ + + (void) seteuid((uid_t)0); + if (logged_in) + logwtmp(ttyline, "", ""); + pw = NULL; + logged_in = 0; + guest = 0; +} + +void +pass(passwd) + char *passwd; +{ + char *salt, *xpasswd; + FILE *fd; + + if (logged_in || askpasswd == 0) { + reply(503, "Login with USER first."); + return; + } + askpasswd = 0; + if (!guest) { /* "ftp" is only account allowed no password */ + if (pw == NULL) + salt = "xx"; + else + salt = pw->pw_passwd; + xpasswd = crypt(passwd, salt); + /* The strcmp does not catch null passwords! */ + if (pw == NULL || *pw->pw_passwd == '\0' || + strcmp(xpasswd, pw->pw_passwd)) { + reply(530, "Login incorrect."); + if (logging) + syslog(LOG_NOTICE, + "FTP LOGIN FAILED FROM %s, %s", + remotehost, curname); + pw = NULL; + if (login_attempts++ >= 5) { + syslog(LOG_NOTICE, + "repeated login failures from %s", + remotehost); + exit(0); + } + return; + } + } + login_attempts = 0; /* this time successful */ + if (setegid((gid_t)pw->pw_gid) < 0) { + reply(550, "Can't set gid."); + return; + } + (void) initgroups(pw->pw_name, pw->pw_gid); + + /* open wtmp before chroot */ + (void)sprintf(ttyline, "ftp%d", getpid()); + logwtmp(ttyline, pw->pw_name, remotehost); + logged_in = 1; + + if (guest) { + /* + * We MUST do a chdir() after the chroot. Otherwise + * the old current directory will be accessible as "." + * outside the new root! + */ + if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + reply(550, "Can't set guest privileges."); + goto bad; + } + } else if (chdir(pw->pw_dir) < 0) { + if (chdir("/") < 0) { + reply(530, "User %s: can't change directory to %s.", + pw->pw_name, pw->pw_dir); + goto bad; + } else + lreply(230, "No directory! Logging in with home=/"); + } + if (seteuid((uid_t)pw->pw_uid) < 0) { + reply(550, "Can't set uid."); + goto bad; + } + /* + * Display a login message, if it exists. + * N.B. reply(230,) must follow the message. + */ + if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { + char *cp, line[LINE_MAX]; + + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(230, "%s", line); + } + (void) fflush(stdout); + (void) fclose(fd); + } + if (guest) { + reply(230, "Guest login ok, access restrictions apply."); +#ifdef SETPROCTITLE + snprintf(proctitle, sizeof(proctitle), + "%s: anonymous/%.*s", remotehost, + sizeof(proctitle) - sizeof(remotehost) - + sizeof(": anonymous/"), passwd); + setproctitle("%s", proctitle); +#endif /* SETPROCTITLE */ + if (logging) + syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", + remotehost, passwd); + } else { + reply(230, "User %s logged in.", pw->pw_name); +#ifdef SETPROCTITLE + snprintf(proctitle, sizeof(proctitle), + "%s: %s", remotehost, pw->pw_name); + setproctitle("%s", proctitle); +#endif /* SETPROCTITLE */ + if (logging) + syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", + remotehost, pw->pw_name); + } + (void) umask(defumask); + return; +bad: + /* Forget all about it... */ + end_login(); +} + +void +retrieve(cmd, name) + char *cmd, *name; +{ + FILE *fin, *dout; + struct stat st; + int (*closefunc) __P((FILE *)); + + if (cmd == 0) { + fin = fopen(name, "r"), closefunc = fclose; + st.st_size = 0; + } else { + char line[BUFSIZ]; + + (void) sprintf(line, cmd, name), name = line; + fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose; + st.st_size = -1; + st.st_blksize = BUFSIZ; + } + if (fin == NULL) { + if (errno != 0) { + perror_reply(550, name); + if (cmd == 0) { + LOGCMD("get", name); + } + } + return; + } + byte_count = -1; + if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) { + reply(550, "%s: not a plain file.", name); + goto done; + } + if (restart_point) { + if (type == TYPE_A) { + off_t i, n; + int c; + + n = restart_point; + i = 0; + while (i++ < n) { + if ((c=getc(fin)) == EOF) { + perror_reply(550, name); + goto done; + } + if (c == '\n') + i++; + } + } else if (lseek(fileno(fin), restart_point, L_SET) < 0) { + perror_reply(550, name); + goto done; + } + } + dout = dataconn(name, st.st_size, "w"); + if (dout == NULL) + goto done; + send_data(fin, dout, st.st_blksize); + (void) fclose(dout); + data = -1; + pdata = -1; +done: + if (cmd == 0) + LOGBYTES("get", name, byte_count); + (*closefunc)(fin); +} + +void +store(name, mode, unique) + char *name, *mode; + int unique; +{ + FILE *fout, *din; + struct stat st; + int (*closefunc) __P((FILE *)); + + if (unique && stat(name, &st) == 0 && + (name = gunique(name)) == NULL) { + LOGCMD(*mode == 'w' ? "put" : "append", name); + return; + } + + if (restart_point) + mode = "r+"; + fout = fopen(name, mode); + closefunc = fclose; + if (fout == NULL) { + perror_reply(553, name); + LOGCMD(*mode == 'w' ? "put" : "append", name); + return; + } + byte_count = -1; + if (restart_point) { + if (type == TYPE_A) { + off_t i, n; + int c; + + n = restart_point; + i = 0; + while (i++ < n) { + if ((c=getc(fout)) == EOF) { + perror_reply(550, name); + goto done; + } + if (c == '\n') + i++; + } + /* + * We must do this seek to "current" position + * because we are changing from reading to + * writing. + */ + if (fseek(fout, 0L, L_INCR) < 0) { + perror_reply(550, name); + goto done; + } + } else if (lseek(fileno(fout), restart_point, L_SET) < 0) { + perror_reply(550, name); + goto done; + } + } + din = dataconn(name, (off_t)-1, "r"); + if (din == NULL) + goto done; + if (receive_data(din, fout) == 0) { + if (unique) + reply(226, "Transfer complete (unique file name:%s).", + name); + else + reply(226, "Transfer complete."); + } + (void) fclose(din); + data = -1; + pdata = -1; +done: + LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count); + (*closefunc)(fout); +} + +static FILE * +getdatasock(mode) + char *mode; +{ + int on = 1, s, t, tries; + + if (data >= 0) + return (fdopen(data, mode)); + (void) seteuid((uid_t)0); + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + goto bad; + if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (char *) &on, sizeof(on)) < 0) + goto bad; + /* anchor socket to avoid multi-homing problems */ + data_source.sin_family = AF_INET; + data_source.sin_addr = ctrl_addr.sin_addr; + for (tries = 1; ; tries++) { + if (bind(s, (struct sockaddr *)&data_source, + sizeof(data_source)) >= 0) + break; + if (errno != EADDRINUSE || tries > 10) + goto bad; + sleep(tries); + } + (void) seteuid((uid_t)pw->pw_uid); +#ifdef IP_TOS + on = IPTOS_THROUGHPUT; + if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); +#endif + return (fdopen(s, mode)); +bad: + /* Return the real value of errno (close may change it) */ + t = errno; + (void) seteuid((uid_t)pw->pw_uid); + (void) close(s); + errno = t; + return (NULL); +} + +static FILE * +dataconn(name, size, mode) + char *name; + off_t size; + char *mode; +{ + char sizebuf[32]; + FILE *file; + int retry = 0, tos; + + file_size = size; + byte_count = 0; + if (size != (off_t) -1) + (void) sprintf(sizebuf, " (%qd bytes)", size); + else + (void) strcpy(sizebuf, ""); + if (pdata >= 0) { + struct sockaddr_in from; + int s, fromlen = sizeof(from); + + s = accept(pdata, (struct sockaddr *)&from, &fromlen); + if (s < 0) { + reply(425, "Can't open data connection."); + (void) close(pdata); + pdata = -1; + return (NULL); + } + (void) close(pdata); + pdata = s; +#ifdef IP_TOS + tos = IPTOS_LOWDELAY; + (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, + sizeof(int)); +#endif + reply(150, "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + return (fdopen(pdata, mode)); + } + if (data >= 0) { + reply(125, "Using existing data connection for '%s'%s.", + name, sizebuf); + usedefault = 1; + return (fdopen(data, mode)); + } + if (usedefault) + data_dest = his_addr; + usedefault = 1; + file = getdatasock(mode); + if (file == NULL) { + reply(425, "Can't create data socket (%s,%d): %s.", + inet_ntoa(data_source.sin_addr), + ntohs(data_source.sin_port), strerror(errno)); + return (NULL); + } + data = fileno(file); + while (connect(data, (struct sockaddr *)&data_dest, + sizeof(data_dest)) < 0) { + if (errno == EADDRINUSE && retry < swaitmax) { + sleep((unsigned) swaitint); + retry += swaitint; + continue; + } + perror_reply(425, "Can't build data connection"); + (void) fclose(file); + data = -1; + return (NULL); + } + reply(150, "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + return (file); +} + +/* + * Tranfer the contents of "instr" to "outstr" peer using the appropriate + * encapsulation of the data subject * to Mode, Structure, and Type. + * + * NB: Form isn't handled. + */ +static void +send_data(instr, outstr, blksize) + FILE *instr, *outstr; + off_t blksize; +{ + int c, cnt, filefd, netfd; + char *buf; + + transflag++; + if (setjmp(urgcatch)) { + transflag = 0; + return; + } + switch (type) { + + case TYPE_A: + while ((c = getc(instr)) != EOF) { + byte_count++; + if (c == '\n') { + if (ferror(outstr)) + goto data_err; + (void) putc('\r', outstr); + } + (void) putc(c, outstr); + } + fflush(outstr); + transflag = 0; + if (ferror(instr)) + goto file_err; + if (ferror(outstr)) + goto data_err; + reply(226, "Transfer complete."); + return; + + case TYPE_I: + case TYPE_L: + if ((buf = malloc((u_int)blksize)) == NULL) { + transflag = 0; + perror_reply(451, "Local resource failure: malloc"); + return; + } + netfd = fileno(outstr); + filefd = fileno(instr); + while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && + write(netfd, buf, cnt) == cnt) + byte_count += cnt; + transflag = 0; + (void)free(buf); + if (cnt != 0) { + if (cnt < 0) + goto file_err; + goto data_err; + } + reply(226, "Transfer complete."); + return; + default: + transflag = 0; + reply(550, "Unimplemented TYPE %d in send_data", type); + return; + } + +data_err: + transflag = 0; + perror_reply(426, "Data connection"); + return; + +file_err: + transflag = 0; + perror_reply(551, "Error on input file"); +} + +/* + * Transfer data from peer to "outstr" using the appropriate encapulation of + * the data subject to Mode, Structure, and Type. + * + * N.B.: Form isn't handled. + */ +static int +receive_data(instr, outstr) + FILE *instr, *outstr; +{ + int c; + int cnt, bare_lfs = 0; + char buf[BUFSIZ]; + + transflag++; + if (setjmp(urgcatch)) { + transflag = 0; + return (-1); + } + switch (type) { + + case TYPE_I: + case TYPE_L: + while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) { + if (write(fileno(outstr), buf, cnt) != cnt) + goto file_err; + byte_count += cnt; + } + if (cnt < 0) + goto data_err; + transflag = 0; + return (0); + + case TYPE_E: + reply(553, "TYPE E not implemented."); + transflag = 0; + return (-1); + + case TYPE_A: + while ((c = getc(instr)) != EOF) { + byte_count++; + if (c == '\n') + bare_lfs++; + while (c == '\r') { + if (ferror(outstr)) + goto data_err; + if ((c = getc(instr)) != '\n') { + (void) putc ('\r', outstr); + if (c == '\0' || c == EOF) + goto contin2; + } + } + (void) putc(c, outstr); + contin2: ; + } + fflush(outstr); + if (ferror(instr)) + goto data_err; + if (ferror(outstr)) + goto file_err; + transflag = 0; + if (bare_lfs) { + lreply(226, + "WARNING! %d bare linefeeds received in ASCII mode", + bare_lfs); + (void)printf(" File may not have transferred correctly.\r\n"); + } + return (0); + default: + reply(550, "Unimplemented TYPE %d in receive_data", type); + transflag = 0; + return (-1); + } + +data_err: + transflag = 0; + perror_reply(426, "Data Connection"); + return (-1); + +file_err: + transflag = 0; + perror_reply(452, "Error writing file"); + return (-1); +} + +void +statfilecmd(filename) + char *filename; +{ + FILE *fin; + int c; + char line[LINE_MAX]; + + (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename); + fin = ftpd_popen(line, "r"); + lreply(211, "status of %s:", filename); + while ((c = getc(fin)) != EOF) { + if (c == '\n') { + if (ferror(stdout)){ + perror_reply(421, "control connection"); + (void) ftpd_pclose(fin); + dologout(1); + /* NOTREACHED */ + } + if (ferror(fin)) { + perror_reply(551, filename); + (void) ftpd_pclose(fin); + return; + } + (void) putc('\r', stdout); + } + (void) putc(c, stdout); + } + (void) ftpd_pclose(fin); + reply(211, "End of Status"); +} + +void +statcmd() +{ + struct sockaddr_in *sin; + u_char *a, *p; + + lreply(211, "%s FTP server status:", hostname, version); + printf(" %s\r\n", version); + printf(" Connected to %s", remotehost); + if (!isdigit(remotehost[0])) + printf(" (%s)", inet_ntoa(his_addr.sin_addr)); + printf("\r\n"); + if (logged_in) { + if (guest) + printf(" Logged in anonymously\r\n"); + else + printf(" Logged in as %s\r\n", pw->pw_name); + } else if (askpasswd) + printf(" Waiting for password\r\n"); + else + printf(" Waiting for user name\r\n"); + printf(" TYPE: %s", typenames[type]); + if (type == TYPE_A || type == TYPE_E) + printf(", FORM: %s", formnames[form]); + if (type == TYPE_L) +#if NBBY == 8 + printf(" %d", NBBY); +#else + printf(" %d", bytesize); /* need definition! */ +#endif + printf("; STRUcture: %s; transfer MODE: %s\r\n", + strunames[stru], modenames[mode]); + if (data != -1) + printf(" Data connection open\r\n"); + else if (pdata != -1) { + printf(" in Passive mode"); + sin = &pasv_addr; + goto printaddr; + } else if (usedefault == 0) { + printf(" PORT"); + sin = &data_dest; +printaddr: + a = (u_char *) &sin->sin_addr; + p = (u_char *) &sin->sin_port; +#define UC(b) (((int) b) & 0xff) + printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), + UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); +#undef UC + } else + printf(" No data connection\r\n"); + reply(211, "End of status"); +} + +void +fatal(s) + char *s; +{ + + reply(451, "Error in server: %s\n", s); + reply(221, "Closing connection due to server error."); + dologout(0); + /* NOTREACHED */ +} + +void +#if __STDC__ +reply(int n, const char *fmt, ...) +#else +reply(n, fmt, va_alist) + int n; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)printf("%d ", n); + (void)vprintf(fmt, ap); + (void)printf("\r\n"); + (void)fflush(stdout); + if (debug) { + syslog(LOG_DEBUG, "<--- %d ", n); + vsyslog(LOG_DEBUG, fmt, ap); + } +} + +void +#if __STDC__ +lreply(int n, const char *fmt, ...) +#else +lreply(n, fmt, va_alist) + int n; + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)printf("%d- ", n); + (void)vprintf(fmt, ap); + (void)printf("\r\n"); + (void)fflush(stdout); + if (debug) { + syslog(LOG_DEBUG, "<--- %d- ", n); + vsyslog(LOG_DEBUG, fmt, ap); + } +} + +static void +ack(s) + char *s; +{ + + reply(250, "%s command successful.", s); +} + +void +nack(s) + char *s; +{ + + reply(502, "%s command not implemented.", s); +} + +/* ARGSUSED */ +void +yyerror(s) + char *s; +{ + char *cp; + + if (cp = strchr(cbuf,'\n')) + *cp = '\0'; + reply(500, "'%s': command not understood.", cbuf); +} + +void +delete(name) + char *name; +{ + struct stat st; + + LOGCMD("delete", name); + if (stat(name, &st) < 0) { + perror_reply(550, name); + return; + } + if ((st.st_mode&S_IFMT) == S_IFDIR) { + if (rmdir(name) < 0) { + perror_reply(550, name); + return; + } + goto done; + } + if (unlink(name) < 0) { + perror_reply(550, name); + return; + } +done: + ack("DELE"); +} + +void +cwd(path) + char *path; +{ + + if (chdir(path) < 0) + perror_reply(550, path); + else + ack("CWD"); +} + +void +makedir(name) + char *name; +{ + + LOGCMD("mkdir", name); + if (mkdir(name, 0777) < 0) + perror_reply(550, name); + else + reply(257, "MKD command successful."); +} + +void +removedir(name) + char *name; +{ + + LOGCMD("rmdir", name); + if (rmdir(name) < 0) + perror_reply(550, name); + else + ack("RMD"); +} + +void +pwd() +{ + char path[MAXPATHLEN]; + + if (getcwd(path, sizeof(path)) == (char *)NULL) + reply(550, "%s.", path); + else + reply(257, "\"%s\" is current directory.", path); +} + +char * +renamefrom(name) + char *name; +{ + struct stat st; + + if (stat(name, &st) < 0) { + perror_reply(550, name); + return ((char *)0); + } + reply(350, "File exists, ready for destination name"); + return (name); +} + +void +renamecmd(from, to) + char *from, *to; +{ + + LOGCMD2("rename", from, to); + if (rename(from, to) < 0) + perror_reply(550, "rename"); + else + ack("RNTO"); +} + +static void +dolog(sin) + struct sockaddr_in *sin; +{ + struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof(struct in_addr), AF_INET); + + if (hp) + (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)); + else + (void) strncpy(remotehost, inet_ntoa(sin->sin_addr), + sizeof(remotehost)); +#ifdef SETPROCTITLE + snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost); + setproctitle("%s", proctitle); +#endif /* SETPROCTITLE */ + + if (logging) + syslog(LOG_INFO, "connection from %s", remotehost); +} + +/* + * Record logout in wtmp file + * and exit with supplied status. + */ +void +dologout(status) + int status; +{ + /* + * Prevent reception of SIGURG from resulting in a resumption + * back to the main program loop. + */ + transflag = 0; + + if (logged_in) { + (void) seteuid((uid_t)0); + logwtmp(ttyline, "", ""); + } + /* beware of flushing buffers after a SIGPIPE */ + _exit(status); +} + +static void +myoob(signo) + int signo; +{ + char *cp; + + /* only process if transfer occurring */ + if (!transflag) + return; + cp = tmpline; + if (getline(cp, 7, stdin) == NULL) { + reply(221, "You could at least say goodbye."); + dologout(0); + } + upper(cp); + if (strcmp(cp, "ABOR\r\n") == 0) { + tmpline[0] = '\0'; + reply(426, "Transfer aborted. Data connection closed."); + reply(226, "Abort successful"); + longjmp(urgcatch, 1); + } + if (strcmp(cp, "STAT\r\n") == 0) { + if (file_size != (off_t) -1) + reply(213, "Status: %qd of %qd bytes transferred", + byte_count, file_size); + else + reply(213, "Status: %qd bytes transferred", byte_count); + } +} + +/* + * Note: a response of 425 is not mentioned as a possible response to + * the PASV command in RFC959. However, it has been blessed as + * a legitimate response by Jon Postel in a telephone conversation + * with Rick Adams on 25 Jan 89. + */ +void +passive() +{ + int len; + char *p, *a; + + pdata = socket(AF_INET, SOCK_STREAM, 0); + if (pdata < 0) { + perror_reply(425, "Can't open passive connection"); + return; + } + pasv_addr = ctrl_addr; + pasv_addr.sin_port = 0; + (void) seteuid((uid_t)0); + if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { + (void) seteuid((uid_t)pw->pw_uid); + goto pasv_error; + } + (void) seteuid((uid_t)pw->pw_uid); + len = sizeof(pasv_addr); + if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) + goto pasv_error; + if (listen(pdata, 1) < 0) + goto pasv_error; + a = (char *) &pasv_addr.sin_addr; + p = (char *) &pasv_addr.sin_port; + +#define UC(b) (((int) b) & 0xff) + + reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), + UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); + return; + +pasv_error: + (void) close(pdata); + pdata = -1; + perror_reply(425, "Can't open passive connection"); + return; +} + +/* + * Generate unique name for file with basename "local". + * The file named "local" is already known to exist. + * Generates failure reply on error. + */ +static char * +gunique(local) + char *local; +{ + static char new[MAXPATHLEN]; + struct stat st; + int count; + char *cp; + + cp = strrchr(local, '/'); + if (cp) + *cp = '\0'; + if (stat(cp ? local : ".", &st) < 0) { + perror_reply(553, cp ? local : "."); + return ((char *) 0); + } + if (cp) + *cp = '/'; + (void) strcpy(new, local); + cp = new + strlen(new); + *cp++ = '.'; + for (count = 1; count < 100; count++) { + (void)sprintf(cp, "%d", count); + if (stat(new, &st) < 0) + return (new); + } + reply(452, "Unique file name cannot be created."); + return (NULL); +} + +/* + * Format and send reply containing system error number. + */ +void +perror_reply(code, string) + int code; + char *string; +{ + + reply(code, "%s: %s.", string, strerror(errno)); +} + +static char *onefile[] = { + "", + 0 +}; + +void +send_file_list(whichf) + char *whichf; +{ + struct stat st; + DIR *dirp = NULL; + struct dirent *dir; + FILE *dout = NULL; + char **dirlist, *dirname; + int simple = 0; + int freeglob = 0; + glob_t gl; + + if (strpbrk(whichf, "~{[*?") != NULL) { + int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + freeglob = 1; + if (glob(whichf, flags, 0, &gl)) { + reply(550, "not found"); + goto out; + } else if (gl.gl_pathc == 0) { + errno = ENOENT; + perror_reply(550, whichf); + goto out; + } + dirlist = gl.gl_pathv; + } else { + onefile[0] = whichf; + dirlist = onefile; + simple = 1; + } + + if (setjmp(urgcatch)) { + transflag = 0; + goto out; + } + while (dirname = *dirlist++) { + if (stat(dirname, &st) < 0) { + /* + * If user typed "ls -l", etc, and the client + * used NLST, do what the user meant. + */ + if (dirname[0] == '-' && *dirlist == NULL && + transflag == 0) { + retrieve("/bin/ls %s", dirname); + goto out; + } + perror_reply(550, whichf); + if (dout != NULL) { + (void) fclose(dout); + transflag = 0; + data = -1; + pdata = -1; + } + goto out; + } + + if (S_ISREG(st.st_mode)) { + if (dout == NULL) { + dout = dataconn("file list", (off_t)-1, "w"); + if (dout == NULL) + goto out; + transflag++; + } + fprintf(dout, "%s%s\n", dirname, + type == TYPE_A ? "\r" : ""); + byte_count += strlen(dirname) + 1; + continue; + } else if (!S_ISDIR(st.st_mode)) + continue; + + if ((dirp = opendir(dirname)) == NULL) + continue; + + while ((dir = readdir(dirp)) != NULL) { + char nbuf[MAXPATHLEN]; + + if (dir->d_name[0] == '.' && dir->d_namlen == 1) + continue; + if (dir->d_name[0] == '.' && dir->d_name[1] == '.' && + dir->d_namlen == 2) + continue; + + sprintf(nbuf, "%s/%s", dirname, dir->d_name); + + /* + * We have to do a stat to insure it's + * not a directory or special file. + */ + if (simple || (stat(nbuf, &st) == 0 && + S_ISREG(st.st_mode))) { + if (dout == NULL) { + dout = dataconn("file list", (off_t)-1, + "w"); + if (dout == NULL) + goto out; + transflag++; + } + if (nbuf[0] == '.' && nbuf[1] == '/') + fprintf(dout, "%s%s\n", &nbuf[2], + type == TYPE_A ? "\r" : ""); + else + fprintf(dout, "%s%s\n", nbuf, + type == TYPE_A ? "\r" : ""); + byte_count += strlen(nbuf) + 1; + } + } + (void) closedir(dirp); + } + + if (dout == NULL) + reply(550, "No files found."); + else if (ferror(dout) != 0) + perror_reply(550, "Data connection"); + else + reply(226, "Transfer complete."); + + transflag = 0; + if (dout != NULL) + (void) fclose(dout); + data = -1; + pdata = -1; +out: + if (freeglob) { + freeglob = 0; + globfree(&gl); + } +} + +#ifdef SETPROCTITLE +/* + * Clobber argv so ps will show what we're doing. (Stolen from sendmail.) + * Warning, since this is usually started from inetd.conf, it often doesn't + * have much of an environment or arglist to overwrite. + */ +void +#if __STDC__ +setproctitle(const char *fmt, ...) +#else +setproctitle(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + int i; + va_list ap; + char *p, *bp, ch; + char buf[LINE_MAX]; + +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)vsnprintf(buf, sizeof(buf), fmt, ap); + + /* make ps print our process name */ + p = Argv[0]; + *p++ = '-'; + + i = strlen(buf); + if (i > LastArgv - p - 2) { + i = LastArgv - p - 2; + buf[i] = '\0'; + } + bp = buf; + while (ch = *bp++) + if (ch != '\n' && ch != '\r') + *p++ = ch; + while (p < LastArgv) + *p++ = ' '; +} +#endif /* SETPROCTITLE */ +#pragma CC_OPT_RESTORE diff --git a/ftpd.tproj/logwtmp.c b/ftpd.tproj/logwtmp.c new file mode 100644 index 0000000..cca4d26 --- /dev/null +++ b/ftpd.tproj/logwtmp.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef lint +static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include "extern.h" + +static int fd = -1; + +/* + * Modified version of logwtmp that holds wtmp file open + * after first call, for use with ftp (which may chroot + * after login, but before logout). + */ +void +logwtmp(line, name, host) + char *line, *name, *host; +{ + struct utmp ut; + struct stat buf; + + if (fd < 0 && (fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0)) < 0) + return; + if (fstat(fd, &buf) == 0) { + (void)strncpy(ut.ut_line, line, sizeof(ut.ut_line)); + (void)strncpy(ut.ut_name, name, sizeof(ut.ut_name)); + (void)strncpy(ut.ut_host, host, sizeof(ut.ut_host)); + (void)time(&ut.ut_time); + if (write(fd, (char *)&ut, sizeof(struct utmp)) != + sizeof(struct utmp)) + (void)ftruncate(fd, buf.st_size); + } +} diff --git a/ftpd.tproj/pathnames.h b/ftpd.tproj/pathnames.h new file mode 100644 index 0000000..56868c4 --- /dev/null +++ b/ftpd.tproj/pathnames.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + */ + +#include + +#define _PATH_FTPUSERS "/etc/ftpusers" +#define _PATH_FTPWELCOME "/etc/ftpwelcome" +#define _PATH_FTPLOGINMESG "/etc/motd" diff --git a/ftpd.tproj/popen.c b/ftpd.tproj/popen.c new file mode 100644 index 0000000..dab3d3f --- /dev/null +++ b/ftpd.tproj/popen.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software written by Ken Arnold and + * published in UNIX Review, Vol. 6, No. 8. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef lint +static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +/* + * Special version of popen which avoids call to shell. This ensures noone + * may create a pipe to a hidden program as a side effect of a list or dir + * command. + */ +static int *pids; +static int fds; + +FILE * +ftpd_popen(program, type) + char *program, *type; +{ + char *cp; + FILE *iop; + int argc, gargc, pdes[2], pid; + char **pop, *argv[100], *gargv[1000]; + + if (*type != 'r' && *type != 'w' || type[1]) + return (NULL); + + if (!pids) { + if ((fds = getdtablesize()) <= 0) + return (NULL); + if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL) + return (NULL); + memset(pids, 0, fds * sizeof(int)); + } + if (pipe(pdes) < 0) + return (NULL); + + /* break up string into pieces */ + for (argc = 0, cp = program;; cp = NULL) + if (!(argv[argc++] = strtok(cp, " \t\n"))) + break; + + /* glob each piece */ + gargv[0] = argv[0]; + for (gargc = argc = 1; argv[argc]; argc++) { + glob_t gl; + int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE; + + memset(&gl, 0, sizeof(gl)); + if (glob(argv[argc], flags, NULL, &gl)) + gargv[gargc++] = strdup(argv[argc]); + else + for (pop = gl.gl_pathv; *pop; pop++) + gargv[gargc++] = strdup(*pop); + globfree(&gl); + } + gargv[gargc] = NULL; + + iop = NULL; + switch(pid = vfork()) { + case -1: /* error */ + (void)close(pdes[0]); + (void)close(pdes[1]); + goto pfree; + /* NOTREACHED */ + case 0: /* child */ + if (*type == 'r') { + if (pdes[1] != STDOUT_FILENO) { + dup2(pdes[1], STDOUT_FILENO); + (void)close(pdes[1]); + } + dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */ + (void)close(pdes[0]); + } else { + if (pdes[0] != STDIN_FILENO) { + dup2(pdes[0], STDIN_FILENO); + (void)close(pdes[0]); + } + (void)close(pdes[1]); + } + execv(gargv[0], gargv); + _exit(1); + } + /* parent; assume fdopen can't fail... */ + if (*type == 'r') { + iop = fdopen(pdes[0], type); + (void)close(pdes[1]); + } else { + iop = fdopen(pdes[1], type); + (void)close(pdes[0]); + } + pids[fileno(iop)] = pid; + +pfree: for (argc = 1; gargv[argc] != NULL; argc++) + free(gargv[argc]); + + return (iop); +} + +int +ftpd_pclose(iop) + FILE *iop; +{ + int fdes, omask, status; + pid_t pid; + + /* + * pclose returns -1 if stream is not associated with a + * `popened' command, or, if already `pclosed'. + */ + if (pids == 0 || pids[fdes = fileno(iop)] == 0) + return (-1); + (void)fclose(iop); + omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); + while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR) + continue; + (void)sigsetmask(omask); + pids[fdes] = 0; + if (pid < 0) + return (pid); + if (WIFEXITED(status)) + return (WEXITSTATUS(status)); + return (1); +} diff --git a/ftpd.tproj/vers.c b/ftpd.tproj/vers.c new file mode 100644 index 0000000..ee00fa9 --- /dev/null +++ b/ftpd.tproj/vers.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)vers.c 5.1 (Berkeley) 6/24/90";*/ +static char rcsid[] = "$Id: vers.c,v 1.1.1.1 1999/05/02 03:57:40 wsanchez Exp $"; +#endif /* not lint */ + +char version[] = "Version 5.60"; diff --git a/identd.tproj/CREDITS b/identd.tproj/CREDITS new file mode 100644 index 0000000..c117a03 --- /dev/null +++ b/identd.tproj/CREDITS @@ -0,0 +1,52 @@ +Credits go to (I've probably forgot someone - please don't hesitate +to tell me!) for helping making Pidentd what it is: + +Casper Dik , Math & CS Faculty, U. of Amsterdam, NL + (Added support for SunOS 5 (Solaris 2)) + +Dave Shield , CS Dept. Liverpool U., UK + (Added support for HP9K HPUX 8.*) + +Jan L. Peterson , Math Dept. BYU, USA + (Added support for MIPS RISC/os and fixed a few other things) + +Fletcher Mattox , University of Texas, USA + (Added support for HP9K HP-UX 7.*) + +Mark Monnin , Rose-Hulman Inst. of Tech, USA + (Added support for DEC Ultrix 4.*) + +Simon Leinen , Switzerland + (Added support for Silicon Graphics IRIX 4.*) + +Frank Maas , Delft Univ. of Technology, The Netherlands + (Added support for Sequent Dynix 3.*) + +Andrew Herbert , Monash University, Australia + (Added support for System V/Release 4) + +David Bennet , Australia + (Added support for 386BSD) + +Fishman M. Shmuel , Technion Inst. of Tech., Israel + (Added support for Convex & 4.3BSDtahoe (then heavily hacked by me)) + +Bradley E. Smith , Bradley University, USA + (Added support for AT&T's own version of SVR4) + +RenE J.V. Bertin , Uni. of Utrecht, The Netherlands + (Added support for Apple A/UX 2.*) + +Douglas Lee Schales , Texas A&M University, USA + (Added support for Cray UNICOS 6.*) + +Don Hazlewood , SW Texas State U., USA + (Added support for A/UX 3.*) + + Nigel Metheringham , University of York, UK + (Added support for NeXT, SunOS 3.*, corrections for MIPS) + +---------------------------------------------------------------------------- +Peter Eriksson , Lysator, Linkoping University, Sweden. + (Original code for Sun SunOS 4.* and Sequent Dynix 2.*) + diff --git a/identd.tproj/Makefile b/identd.tproj/Makefile new file mode 100644 index 0000000..b8d220f --- /dev/null +++ b/identd.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = identd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = error.h identd.h xpaths.h + +CFILES = config.c identd.c netbsd.c parse.c proxy.c version.c + +OTHERSRCS = CREDITS Makefile.dist README identd.8 Makefile.preamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/identd.tproj/Makefile.dist b/identd.tproj/Makefile.dist new file mode 100644 index 0000000..fad1caa --- /dev/null +++ b/identd.tproj/Makefile.dist @@ -0,0 +1,10 @@ +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:57:40 wsanchez Exp $ + +PROG= identd +SRCS= config.c identd.c netbsd.c parse.c proxy.c version.c +MAN8= identd.0 + +LDADD= -lkvm +DPADD= ${LIBKVM} + +.include diff --git a/identd.tproj/Makefile.preamble b/identd.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/identd.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/identd.tproj/PB.project b/identd.tproj/PB.project new file mode 100644 index 0000000..b6dd3a8 --- /dev/null +++ b/identd.tproj/PB.project @@ -0,0 +1,40 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (error.h, identd.h, xpaths.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (config.c, identd.c, netbsd.c, parse.c, proxy.c, version.c); + OTHER_SOURCES = (CREDITS, Makefile.dist, README, identd.8, Makefile.preamble); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = identd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/identd.tproj/README b/identd.tproj/README new file mode 100644 index 0000000..f1e1d3b --- /dev/null +++ b/identd.tproj/README @@ -0,0 +1,129 @@ + pidentd + + ("Peter's Ident Daemon" or is it "Portable Ident Daemon"?) + + Peter Eriksson + + +This program is released into the public domain and can be used by +anyone who wants to. Vendors may include it into their distributions +if they want to without any restrictions. (Although it would be nice +to be notified by email if someone decides to do that, and/or a note +somewhere about who wrote this program. Like in the man-page or so.. :-) + +This is a program that implements the RFC1413 identification server. It +was very much inspired by Dan Bernstein's original 'authd' (but unlike +that program doesn't use 'netstat' to get some of the information) It +uses the kernel information directly. (And is due to that fact a lot +faster). Dan has now written another version of the 'authd' daemon that +uses his 'kstuff' to read the kernel information. Unlike that daemon, +this will use only normally available kernel access functions (and is due +to that more limited in the different machines it support). Please note +that this daemon used to be called pauthd but has changed name to better +reflect what it does (and to conform to the new RFC). + +This daemon has been tested on the following machines/OS (please report +to me if you've tested a newer version, or if your machine/OS isn't among +the ones below): + +Machine Operating System Pidentd version +---------------------- ---------------------- -------------------------- + Sequent Balance Dynix 3.0.14 2.1beta.12 + Sequent Symmetry Dynix 3.1.2 2.1beta.3 + Sun 3/50 SunOS 3.5 2.1beta.8.1 (3) + Sun 386i SunOS 4.0.2 1.9beta + Sun 2/120 SunOS 4.0.3 2.1beta.10 + Sun 3/280 SunOS 4.1.1 2.1beta.12 + Sun 4/380 SunOS 4.1.3 2.1beta.12 + Sun SS1/41 SunOS 5.1 2.1beta.11 + HP 9000/375 HP-UX 7.0 2.1beta.10.1 (1) + HP 9000/300 HP-UX 8.0 2.1beta.12 + HP 9000/340 HP-UX 8.0 2.1beta.10.1 + HP 9000/360 HP-UX 8.0 2.1beta.10.1 + HP 9000/710 HP-UX 8.07 2.1beta.10.1 + HP 9000/720 HP-UX 8.07 2.1beta.10.1 + HP 9000/715 HP-UX 9.0 2.1beta.9.1 + HP 9000/827 HP-UX 8.02 2.1beta.8.1 + HP 9000/834 HP-UX 7.0 2.0beta.4 + HP 9000/835 HP-UX 8.00 2.1beta.10.1 + MIPS RISC/OS 4.5x 2.1beta.8.1 + DECstation 2100 Ultrix 4.2-96 2.1beta.2 (2) + DECstation 5000/133 Ultrix 4.2 2.1beta.9.1 (2) [?] + DEC VAXstation 2000 Ultrix-32 3.1 2.1beta.12 (2) [?] + DEC VAX vs3520 Ultrix 3.0 2.1beta.9.1 (2) [?] + DEC VAX 11/780 4.3BSD Reno 2.1beta.12 (2) + i486-PC UHC SVR4 2.0 2.0beta.4 (2) + i486-PC Dell SVR4 2.2 2.0beta.4 (2) + i486-PC ESIX SVR4 4.0.4 2.1beta.2 (2) + i486-PC 386BSD 0.1 2.1beta.3 (2) + Cray UNICOS 6.0.12 2.1beta.7 + NeXT NeXTSTEP 2.1 2.1beta.9.1 (3) + NeXT NeXTSTEP 3.0 2.1beta.9.1 (3) + Pyramid 90x dualPort OSx 4.1 2.1beta.12 + Silicon Graphics IRIX 4 2.1beta.10 + +Notes: + 1) HP-UX 7.0 doesn't support running streams based services from + Inetd with the "wait" option (and the "-w" flag to Pidentd). + + It also has problems with starting stuff as user "sys" from Inetd. + (It doesn't correctly set the group id to "sys") so I suggest you + either starts it as user "root" and use the "-u" and "-g" flags + to setuid and setgid itself to user "sys", group "sys", or do a + 'chgrp sys in.identd' and then a 'chmod g+s in.identd' and start + it as user "sys" from Inetd. + + 2) These systems also doesn't support running streams based + services from Inetd with the "wait" option. + + 3) See notes in the READMEs/README. specific files. + + +Please let me know if you find any bugs, or have ported it to other +machines (and care to share the changes with me and the world!). + +See the manual page for information about the various command line +options that are available. + +NOTE: One should NOT use the -d option when using it for normal use! + +If you intend to create or modify daemons that use the IDENT protocol +then you may wish to get the "libident" library that contains some +functions to implement the client side of this protocol. It is available +as "libident-*.tar.Z" in "pub/ident/libs" at "ftp.lysator.liu.se". + +There is a mailing list for users of the IDENT(RFC1413)/TAP protocol called +'ident-users@lysator.liu.se' that you may want to consider joining. +Send mail to the address 'ident-users-request@lysator.liu.se' to +join it. This list is intended for generic discussions on using this +protocol and it's associated tools. + +If you only want to receive news about new (non-alpha/beta) releases of +Pidentd then you can join the 'ident-announce@lysator.liu.se' mailing +list. Send mail to the address 'ident-announce-request@lysator.liu.se' to +join it. No discussions will take place on this list. + +I also run a small mailing list for people who wants to act as testers +of new alpha/beta-versions of Pidentd. If you wish to join, please send +mail to the address 'pidentd-testers-request@lysator.liu.se'. (I can always +use more testers, so don't hesitate :-) + +It's a human (namely me :-) that reads the letters sent to *-request. +Please include the full email address to which to wish to have the +letters sent. + +I'm grateful for success/failure stories about installing/compiling this +daemon... + +Information of interrest: + + 1. Machine and operating system type and version. + 2. Command line flags. + 3. Inetd.conf configuration. + 4. Did it work, or not. And if not - what did it report to the + syslog file? (You'll have to add the "-l" option and probably + reconfigure your Syslogd). If you use the "-d" option then + you can see a verbose error if you Telnet into it directly and + send it a query manually. (See the INSTALL file for more information). + +/Peter Eriksson , 5 April 1993 diff --git a/identd.tproj/config.c b/identd.tproj/config.c new file mode 100644 index 0000000..19eec4c --- /dev/null +++ b/identd.tproj/config.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: config.c,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ +** +** config.c This file handles the config file +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 6 Dec 1992 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#include +#include + +#include "error.h" +#include "identd.h" +#include "xpaths.h" + + +int parse_config(path, silent_flag) + char *path; + int silent_flag; +{ + FILE *fp; + + if (!path) + path = PATH_CONFIG; + + fp = fopen(path, "r"); + if (!fp) + { + if (silent_flag) + return 0; + + ERROR1("error opening %s", path); + } + + /* + ** Code should go here to parse the config file data. + ** For now we just ignore the contents... + */ + + + fclose(fp); + return 0; +} diff --git a/identd.tproj/error.h b/identd.tproj/error.h new file mode 100644 index 0000000..d5f1990 --- /dev/null +++ b/identd.tproj/error.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: error.h,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ +** +** error.h Error handling macros +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 19 Aug 1992 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#ifndef __ERROR_H__ +#define __ERROR_H__ + +#include + +#define ERROR(fmt) \ + ((syslog_flag ? (syslog(LOG_ERR, fmt),0) : 0), \ + (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \ + lport, fport), \ + fprintf(stderr, fmt), perror(": "), 0) : \ + (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \ + fflush(stdout), fflush(stderr), exit(1), 0) + + +#define ERROR1(fmt,v1) \ + ((syslog_flag ? (syslog(LOG_ERR, fmt, v1),0) : 0), \ + (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \ + lport, fport), \ + fprintf(stderr, fmt, v1), perror(": "), 0) : \ + (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \ + fflush(stdout), fflush(stderr), exit(1), 0) + +#define ERROR2(fmt,v1,v2) \ + ((syslog_flag ? (syslog(LOG_ERR, fmt, v1, v2),0) : 0), \ + (debug_flag ? (fprintf(stderr, "%d , %d : ERROR : X-DBG : ", \ + lport, fport), \ + fprintf(stderr, fmt, v1, v2), perror(": "), 0) : \ + (printf("%d , %d : ERROR : UNKNOWN-ERROR\r\n", lport, fport), 0)), \ + fflush(stdout), fflush(stderr), exit(1), 0) + +#endif diff --git a/identd.tproj/identd.8 b/identd.tproj/identd.8 new file mode 100644 index 0000000..4bf839c --- /dev/null +++ b/identd.tproj/identd.8 @@ -0,0 +1,238 @@ +.\" @(#)identd.8 1.9 92/02/11 Lysator +.\" Copyright (c) 1992 Peter Eriksson, Lysator, Linkoping University. +.\" This software has been released into the public domain. +.\" +.\" $Id: identd.8,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ +.\" +.TH IDENTD 8 "27 May 1992" +.SH NAME +identd \- TCP/IP IDENT protocol server +.SH SYNOPSIS +.B identd +.RB [ \-i | \-w | \-b ] +.RB [ \-t ] +.RB [ \-u ] +.RB [ \-g ] +.RB [ \-p ] +.RB [ \-a
] +.RB [ \-c ] +.RB [ \-n ] +.RB [ \-o ] +.RB [ \-e ] +.RB [ \-l ] +.RB [ \-V ] +.RB [ \-v ] +.RB [ \-m ] +.RB [ \-N ] +.RB [ \-d ] +.RB [ kernelfile [ kmemfile ] ] +.SH DESCRIPTION +.IX "identd daemon" "" \fLidentd\fP daemon" +.B identd +is a server which implements the +.SM TCP/IP +proposed standard +.SM IDENT +user identification protocol as specified in the +.SM RFC\s0 1413 +document. +.PP +.B identd +operates by looking up specific +.SM TCP/IP +connections and returning the user name of the +process owning the connection. +.SH ARGUMENTS +The +.B -i +flag, which is the default mode, should be used when starting the +daemon from +.B inetd +with the "nowait" option in the +.B /etc/inetd.conf +file. Use of this mode will make +.B inetd +start one +.B identd +daemon for each connection request. +.PP +The +.B -w +flag should be used when starting the daemon from +.B inetd +with the "wait" option in the +.B /etc/inetd.conf +file . This is the prefered mode of +operation since that will start a copy of +.B identd +at the first connection request and then +.B identd +will handle subsequent requests +without having to do the nlist lookup in the kernel file for +every request as in the +.B -i +mode above. The +.B identd +daemon will run either forever, until a bug +makes it crash or a timeout, as specified by the +.B -t +flag, occurs. +.PP +The +.B -b +flag can be used to make the daemon run in standalone mode without +the assistance from +.B inetd. +This mode is the least prefered mode since +a bug or any other fatal condition in the server will make it terminate +and it will then have to be restarted manually. Other than that is has the +same advantage as the +.B -w +mode in that it parses the nlist only once. +.PP +The +.B -t +option is used to specify the timeout limit. This is the number +of seconds a server started with the +.B -w +flag will wait for new connections before terminating. The server is +automatically restarted by +.B inetd +whenever a new connection is requested +if it has terminated. A suitable value for this is 120 (2 minutes), if +used. It defaults to no timeout (ie, will wait forever, or until a +fatal condition occurs in the server). +.PP +The +.B -u +option is used to specify a user id number which the +.B ident +server should +switch to after binding itself to the +.SM TCP/IP +port if using the +.B -b +mode of operation. +.PP +The +.B -g +option is used to specify a group id number which the +.B ident +server should +switch to after binding itself to the +.SM TCP/IP +port if using the +.B -b +mode of operation. +.PP +The +.B -p +option is used to specify an alternative port number to bind to if using +the +.B -b +mode of operation. It can be specified by name or by number. Defaults to the +.SM IDENT +port (113). +.PP +The +.B -a
+option is used to specify the local address to bind the socket to if using +the +.B -b +mode of operation. Can only be specified by IP address and not by domain +name. Defaults to the +.SM INADDR_ANY +address which normally means all local addresses. +.PP +The +.B -V +flag makes +.B identd +display the version number and the exit. +.PP +The +.B -l +flag tells +.B identd +to use the System logging daemon +.B syslogd +for logging purposes. +.PP +The +.B -v +flag causes +.B identd +to log every request made, if the use of +.B syslogd +is enabled. +.PP +The +.B -o +flag tells +.B identd +to not reveal the operating system type it is run on and to instead +always return "OTHER". +.PP +The +.B -e +flag tells +.B identd +to always return "UNKNOWN-ERROR" instead of the "NO-USER" or +"INVALID-PORT" errors. +.PP +The +.B -c +flags tells +.B identd +to add the optional (according to the IDENT protocol) character set +designator to the reply generated. should be a valid character +set as described in the MIME RFC in upper case characters. +.PP +The +.B -n +flags tells +.B identd +to always return user numbers instead of user names if you wish to +keep the user names a secret. +.PP +The +.B -N +flag makes +.B identd +check for a file ".noident" in each homedirectory for a user which the +daemon is about to return the user name for. It that file exists then the +daemon will give the error +.B HIDDEN-USER +instead of the normal USERID response. +.PP +.B -m +flag makes +.B identd +use a mode of operation that will allow multiple requests to be +processed per session. Each request is specified one per line and +the responses will be returned one per line. The connection will not +be closed until the connecting part closes it's end of the line. +PLEASE NOTE THAT THIS MODE VIOLATES THE PROTOCOL SPECIFICATION AS +IT CURRENTLY STANDS. +.PP +The +.B -d +flag enables some debugging code that normally should NOT +be enabled since that breaks the protocol and may reveal information +that should not be available to outsiders. +.PP +.B kernelfile +defaults to the normally running kernel file. +.PP +.B kmemfile +defaults to the memory space of the normally running kernel. +.SH SEE ALSO +.BR inetd.conf (5) +.SH BUGS +The handling of fatal errors could be better. +.PP +If the +.B -N +flag is specified and a user's ".noident" file is not accessible, +then ident information regarding that user will be returned +if requested. diff --git a/identd.tproj/identd.c b/identd.tproj/identd.c new file mode 100644 index 0000000..7380de1 --- /dev/null +++ b/identd.tproj/identd.c @@ -0,0 +1,643 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: identd.c,v 1.1.1.2 2000/01/11 01:48:48 wsanchez Exp $ +** +** identd.c A TCP/IP link identification protocol server +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 22 April 1993 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#if defined(IRIX) || defined(SVR4) || defined(__APPLE__) || defined(__NetBSD__) +# define SIGRETURN_TYPE void +# define SIGRETURN_TYPE_IS_VOID +#else +# define SIGRETURN_TYPE int +#endif + +#ifdef SVR4 +# define STRNET +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifndef _AUX_SOURCE +# include +#endif +#include +#include + +#include +#include + +#include + +#ifndef HPUX7 +# include +#endif + +#if defined(MIPS) || defined(BSD43) +extern int errno; +#endif + +#include "identd.h" +#include "error.h" + +/* Antique unixes do not have these things defined... */ +#ifndef FD_SETSIZE +# define FD_SETSIZE 256 +#endif + +#ifndef FD_SET +# ifndef NFDBITS +# define NFDBITS (sizeof(int) * NBBY) /* bits per mask */ +# endif +# define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#endif + +#ifndef FD_ZERO +# define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +extern char *version; + +extern void *calloc(); +extern void *malloc(); + + +char *path_unix = NULL; +char *path_kmem = NULL; + +int verbose_flag = 0; +int debug_flag = 0; +int syslog_flag = 0; +int multi_flag = 0; +int other_flag = 0; +int unknown_flag = 0; +int number_flag = 0; +int noident_flag = 0; + +int lport = 0; +int fport = 0; + +char *charset_name = NULL; +char *indirect_host = NULL; +char *indirect_password = NULL; + +static int child_pid; + +#ifdef LOG_DAEMON +static int syslog_facility = LOG_DAEMON; +#endif + +/* +** The structure passing convention for GCC is incompatible with +** Suns own C compiler, so we define our own inet_ntoa() function. +** (This should only affect GCC version 1 I think, a well, this works +** for version 2 also so why bother.. :-) +*/ +#if defined(__GNUC__) && defined(__sparc__) + +#ifdef inet_ntoa +#undef inet_ntoa +#endif + +char *inet_ntoa(ad) + struct in_addr ad; +{ + unsigned long int s_ad; + int a, b, c, d; + static char addr[20]; + + s_ad = ad.s_addr; + d = s_ad % 256; + s_ad /= 256; + c = s_ad % 256; + s_ad /= 256; + b = s_ad % 256; + a = s_ad / 256; + sprintf(addr, "%d.%d.%d.%d", a, b, c, d); + + return addr; +} +#endif + + +/* +** Return the name of the connecting host, or the IP number as a string. +*/ +char *gethost(addr) + struct in_addr *addr; +{ + struct hostent *hp; + + + hp = gethostbyaddr((char *) addr, sizeof(struct in_addr), AF_INET); + if (hp) + return hp->h_name; + else + return inet_ntoa(*addr); +} + +/* +** Exit cleanly after our time's up. +*/ +static SIGRETURN_TYPE +alarm_handler() +{ + if (syslog_flag) + syslog(LOG_DEBUG, "SIGALRM triggered, exiting"); + + exit(0); +} + +#if !defined(hpux) && !defined(__hpux) && !defined(SVR4) || defined(_CRAY) +/* +** This is used to clean up zombie child processes +** if the -w or -b options are used. +*/ +static SIGRETURN_TYPE +child_handler() +{ +#if defined(IRIX) || defined(__APPLE__) + union wait status; +#else + int status; +#endif + + while (wait3(&status, WNOHANG, NULL) > 0) + ; + +#ifndef SIGRETURN_TYPE_IS_VOID + return 0; +#endif +} +#endif + + +char *clearmem(bp, len) + char *bp; + int len; +{ + char *cp; + + cp = bp; + while (len-- > 0) + *cp++ = 0; + + return bp; +} + + +/* +** Main entry point into this daemon +*/ +int main(argc,argv) + int argc; + char *argv[]; +{ + int i, len; + struct sockaddr_in sin; + struct in_addr laddr, faddr; + struct timeval tv; + + int background_flag = 0; + int timeout = 0; + char *portno = "113"; + char *bind_address = NULL; + int set_uid = 0; + int set_gid = 0; + int inhibit_default_config = 0; + int opt_count = 0; /* Count of option flags */ + +#ifdef __convex__ + argc--; /* get rid of extra argument passed by inetd */ +#endif + + /* + ** Prescan the arguments for "-f" switches + */ + inhibit_default_config = 0; + for (i = 1; i < argc && argv[i][0] == '-'; i++) + if (argv[i][1] == 'f') + inhibit_default_config = 1; + + /* + ** Parse the default config file - if it exists + */ + if (!inhibit_default_config) + parse_config(NULL, 1); + + /* + ** Parse the command line arguments + */ + for (i = 1; i < argc && argv[i][0] == '-'; i++) { + opt_count++; + switch (argv[i][1]) + { + case 'b': /* Start as standalone daemon */ + background_flag = 1; + break; + + case 'w': /* Start from Inetd, wait mode */ + background_flag = 2; + break; + + case 'i': /* Start from Inetd, nowait mode */ + background_flag = 0; + break; + + case 't': + timeout = atoi(argv[i]+2); + break; + + case 'p': + portno = argv[i]+2; + break; + + case 'a': + bind_address = argv[i]+2; + break; + + case 'u': + if (isdigit(argv[i][2])) + set_uid = atoi(argv[i]+2); + else + { + struct passwd *pwd; + + pwd = getpwnam(argv[i]+2); + if (!pwd) + ERROR1("no such user (%s) for -u option", argv[i]+2); + else + { + set_uid = pwd->pw_uid; + set_gid = pwd->pw_gid; + } + } + break; + + case 'g': + if (isdigit(argv[i][2])) + set_gid = atoi(argv[i]+2); + else + { + struct group *grp; + + grp = getgrnam(argv[i]+2); + if (!grp) + ERROR1("no such group (%s) for -g option", argv[i]+2); + else + set_gid = grp->gr_gid; + } + break; + + case 'c': + charset_name = argv[i]+2; + break; + + case 'r': + indirect_host = argv[i]+2; + break; + + case 'l': /* Use the Syslog daemon for logging */ + syslog_flag++; + break; + + case 'o': + other_flag = 1; + break; + + case 'e': + unknown_flag = 1; + break; + + case 'n': + number_flag = 1; + break; + + case 'V': /* Give version of this daemon */ + printf("[in.identd, version %s]\r\n", version); + exit(0); + break; + + case 'v': /* Be verbose */ + verbose_flag++; + break; + + case 'd': /* Enable debugging */ + debug_flag++; + break; + + case 'm': /* Enable multiline queries */ + multi_flag++; + break; + + case 'N': /* Enable users ".noident" files */ + noident_flag++; + break; + } + } + +#if defined(_AUX_SOURCE) || defined (SUNOS35) + /* A/UX 2.0* & SunOS 3.5 calls us with an argument XXXXXXXX.YYYY + ** where XXXXXXXXX is the hexadecimal version of the callers + ** IP number, and YYYY is the port/socket or something. + ** It seems to be impossible to pass arguments to a daemon started + ** by inetd. + ** + ** Just in case it is started from something else, then we only + ** skip the argument if no option flags have been seen. + */ + if (opt_count == 0) + argc--; +#endif + + /* + ** Path to kernel namelist file specified on command line + */ + if (i < argc) + path_unix = argv[i++]; + + /* + ** Path to kernel memory device specified on command line + */ + if (i < argc) + path_kmem = argv[i++]; + + + /* + ** Open the kernel memory device and read the nlist table + */ + if (k_open() < 0) + ERROR("main: k_open"); + + /* + ** Do the special handling needed for the "-b" flag + */ + if (background_flag == 1) + { + struct sockaddr_in addr; + struct servent *sp; + int fd; + + + if (fork()) + exit(0); + + close(0); + close(1); + close(2); + + if (fork()) + exit(0); + + fd = socket(AF_INET, SOCK_STREAM, 0); + if (fd == -1) + ERROR("main: socket"); + + if (fd != 0) + dup2(fd, 0); + + clearmem(&addr, sizeof(addr)); + + addr.sin_family = AF_INET; + if (bind_address == NULL) + addr.sin_addr.s_addr = htonl(INADDR_ANY); + else + { + if (isdigit(bind_address[0])) + addr.sin_addr.s_addr = inet_addr(bind_address); + else + { + struct hostent *hp; + + hp = gethostbyname(bind_address); + if (!hp) + ERROR1("no such address (%s) for -a switch", bind_address); + + /* This is ugly, should use memcpy() or bcopy() but... */ + addr.sin_addr.s_addr = * (unsigned long *) (hp->h_addr); + } + } + + if (isdigit(portno[0])) + addr.sin_port = htons(atoi(portno)); + else + { + sp = getservbyname(portno, "tcp"); + if (sp == NULL) + ERROR1("main: getservbyname: %s", portno); + addr.sin_port = sp->s_port; + } + + if (bind(0, (struct sockaddr *) &addr, sizeof(addr)) < 0) + ERROR("main: bind"); + + if (listen(0, 3) < 0) + ERROR("main: listen"); + } + + if (set_gid) + if (setgid(set_gid) == -1) + ERROR("main: setgid"); + + if (set_uid) + if (setuid(set_uid) == -1) + ERROR("main: setuid"); + + /* + ** Do some special handling if the "-b" or "-w" flags are used + */ + if (background_flag) + { + int nfds, fd; + fd_set read_set; + + + /* + ** Set up the SIGCHLD signal child termination handler so + ** that we can avoid zombie processes hanging around and + ** handle childs terminating before being able to complete the + ** handshake. + */ +#if (defined(SVR4) || defined(hpux) || defined(__hpux) || \ + defined(_CRAY) || defined(_AUX_SOURCE)) + signal(SIGCHLD, SIG_IGN); +#else + signal(SIGCHLD, (SIGRETURN_TYPE (*)()) child_handler); +#endif + + /* + ** Loop and dispatch client handling processes + */ + do + { + /* + ** Terminate if we've been idle for 'timeout' seconds + */ + if (background_flag == 2 && timeout) + { + signal(SIGALRM, alarm_handler); + alarm(timeout); + } + + /* + ** Wait for a connection request to occur. + ** Ignore EINTR (Interrupted System Call). + */ + do + { + FD_ZERO(&read_set); + FD_SET(0, &read_set); + + if (timeout) + { + tv.tv_sec = timeout; + tv.tv_usec = 0; + nfds = select(FD_SETSIZE, &read_set, NULL, NULL, &tv); + } + else + + nfds = select(FD_SETSIZE, &read_set, NULL, NULL, NULL); + } while (nfds < 0 && errno == EINTR); + + /* + ** An error occured in select? Just die + */ + if (nfds < 0) + ERROR("main: select"); + + /* + ** Timeout limit reached. Exit nicely + */ + if (nfds == 0) + exit(0); + + /* + ** Disable the alarm timeout + */ + alarm(0); + + /* + ** Accept the new client + */ + fd = accept(0, NULL, NULL); + if (fd == -1) + ERROR1("main: accept. errno = %d", errno); + + /* + ** And fork, then close the fd if we are the parent. + */ + child_pid = fork(); + } while (child_pid && (close(fd), 1)); + + /* + ** We are now in child, the parent has returned to "do" above. + */ + if (dup2(fd, 0) == -1) + ERROR("main: dup2: failed fd 0"); + + if (dup2(fd, 1) == -1) + ERROR("main: dup2: failed fd 1"); + + if (dup2(fd, 2) == -1) + ERROR("main: dup2: failed fd 2"); + } + + /* + ** Get foreign internet address + */ + len = sizeof(sin); + if (getpeername(0, (struct sockaddr *) &sin, &len) == -1) + { + /* + ** A user has tried to start us from the command line or + ** the network link died, in which case this message won't + ** reach to other end anyway, so lets give the poor user some + ** errors. + */ + perror("in.identd: getpeername()"); + exit(1); + } + + faddr = sin.sin_addr; + + + /* + ** Open the connection to the Syslog daemon if requested + */ + if (syslog_flag) + { +#ifdef LOG_DAEMON + openlog("identd", LOG_PID, syslog_facility); +#else + openlog("identd", LOG_PID); +#endif + + syslog(LOG_INFO, "Connection from %s", gethost(&faddr)); + } + + + /* + ** Get local internet address + */ + len = sizeof(sin); +#ifdef ATTSVR4 + if (t_getsockname(0, (struct sockaddr *) &sin, &len) == -1) +#else + if (getsockname(0, (struct sockaddr *) &sin, &len) == -1) +#endif + { + /* + ** We can just die here, because if this fails then the + ** network has died and we haven't got anyone to return + ** errors to. + */ + exit(1); + } + laddr = sin.sin_addr; + + + /* + ** Get the local/foreign port pair from the luser + */ + parse(stdin, &laddr, &faddr); + + exit(0); +} diff --git a/identd.tproj/identd.h b/identd.tproj/identd.h new file mode 100644 index 0000000..61ece7c --- /dev/null +++ b/identd.tproj/identd.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: identd.h,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ +** +** identd.h Common variables for the Pidentd daemon +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 6 Dec 1992 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#ifndef __IDENTD_H__ +#define __IDENTD_H__ + +extern char *version; + +extern char *path_unix; +extern char *path_kmem; + +extern int verbose_flag; +extern int debug_flag; +extern int syslog_flag; +extern int multi_flag; +extern int other_flag; +extern int unknown_flag; +extern int number_flag; +extern int noident_flag; + +extern char *charset_name; +extern char *indirect_host; +extern char *indirect_password; + +extern int lport; +extern int fport; + +extern char *gethost(); + +extern int k_open(); +extern int k_getuid(); +extern int parse(); +extern int parse_config(); + +#endif diff --git a/identd.tproj/netbsd.c b/identd.tproj/netbsd.c new file mode 100644 index 0000000..83626a4 --- /dev/null +++ b/identd.tproj/netbsd.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: netbsd.c,v 1.1.1.2 2000/01/11 01:48:48 wsanchez Exp $ +** +** netbsd.c Low level kernel access functions for NetBSD +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 17 March 1993 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "kvm.h" + +#include +#include +#include +#include +#include + +#include + +#define KERNEL + +#include + +#undef KERNEL +#include + +#include + +#include + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "identd.h" +#include "error.h" + + +extern void *calloc(); +extern void *malloc(); + + +struct nlist nl[] = +{ +#define N_FILE 0 +#define N_NFILE 1 +#define N_TCB 2 + + { "_filehead" }, + { "_nfiles" }, + { "_tcb" }, + { "" } +}; + +static kvm_t *kd; + +static struct file *xfile; +static int nfile; + +static struct inpcbhead tcb; + + +int k_open() +{ + /* + ** Open the kernel memory device + */ + if ((kd = kvm_openfiles(path_unix, path_kmem, NULL, O_RDONLY, "identd")) == + NULL) + ERROR("main: kvm_open"); + + /* + ** Extract offsets to the needed variables in the kernel + */ + if (kvm_nlist(kd, nl) < 0) + ERROR("main: kvm_nlist"); + + return 0; +} + + +/* +** Get a piece of kernel memory with error handling. +** Returns 1 if call succeeded, else 0 (zero). +*/ +static int getbuf(addr, buf, len, what) + long addr; + char *buf; + int len; + char *what; +{ + if (kvm_read(kd, addr, buf, len) < 0) + { + if (syslog_flag) + syslog(LOG_ERR, "getbuf: kvm_read(%08x, %d) - %s : %m", + addr, len, what); + + return 0; + } + + return 1; +} + + + +/* +** Traverse the inpcb list until a match is found. +** Returns NULL if no match. +*/ +static struct socket * + getlist(pcbp_head, faddr, fport, laddr, lport) + struct inpcbhead *pcbp_head; + struct in_addr *faddr; + int fport; + struct in_addr *laddr; + int lport; +{ + struct inpcb *pcbp; + struct inpcb pcb; + + pcbp = pcbp_head->lh_first; + while (pcbp && + getbuf((long) pcbp, + &pcb, + sizeof(struct inpcb), + "tcblist")) + { + if ( pcb.inp_faddr.s_addr == faddr->s_addr && + pcb.inp_laddr.s_addr == laddr->s_addr && + pcb.inp_fport == fport && + pcb.inp_lport == lport ) + return pcb.inp_socket; + + pcbp = pcb.inp_list.le_next; + } + + return NULL; +} + + + +/* +** Return the user number for the connection owner +*/ +int k_getuid(faddr, fport, laddr, lport, uid) + struct in_addr *faddr; + int fport; + struct in_addr *laddr; + int lport; + int *uid; +{ + long addr; + struct socket *sockp; + int i, mib[2]; + struct ucred ucb; + + /* -------------------- FILE DESCRIPTOR TABLE -------------------- */ + if (!getbuf(nl[N_NFILE].n_value, &nfile, sizeof(nfile), "nfile")) + return -1; + + if (!getbuf(nl[N_FILE].n_value, &addr, sizeof(addr), "&file")) + return -1; + + { + int siz, rv; + + mib[0] = CTL_KERN; + mib[1] = KERN_FILE; + if ((rv = sysctl(mib, 2, NULL, &siz, NULL, 0)) == -1) + { + ERROR1("k_getuid: sysctl 1 (%d)", rv); + return -1; + } + xfile = malloc(siz); + if (!xfile) + ERROR1("k_getuid: malloc(%d)", siz); + if ((rv = sysctl(mib, 2, xfile, &siz, NULL, 0)) == -1) + { + ERROR1("k_getuid: sysctl 2 (%d)", rv); + return -1; + } + xfile = (struct file *)((char *)xfile + sizeof(filehead)); + } + + /* -------------------- TCP PCB LIST -------------------- */ + if (!getbuf(nl[N_TCB].n_value, &tcb, sizeof(tcb), "tcb")) + return -1; + + sockp = getlist(&tcb, faddr, fport, laddr, lport); + + if (!sockp) + return -1; + + /* + ** Locate the file descriptor that has the socket in question + ** open so that we can get the 'ucred' information + */ + for (i = 0; i < nfile; i++) + { + if (xfile[i].f_count == 0) + continue; + + if (xfile[i].f_type == DTYPE_SOCKET && + (struct socket *) xfile[i].f_data == sockp) + { + if (!getbuf(xfile[i].f_cred, &ucb, sizeof(ucb), "ucb")) + return -1; + + *uid = ucb.cr_uid; + return 0; + } + } + + return -1; +} + diff --git a/identd.tproj/parse.c b/identd.tproj/parse.c new file mode 100644 index 0000000..2d978ad --- /dev/null +++ b/identd.tproj/parse.c @@ -0,0 +1,425 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: parse.c,v 1.2 2000/10/03 02:38:32 lindak Exp $ +** +** parse.c This file contains the protocol parser +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 6 Dec 1992 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#include +#include +#include +#include + +#include +#include + +#ifndef HPUX7 +# include +#endif + +#include +#include + +#include +#include + +#if defined(MIPS) || defined(BSD43) +extern int errno; +#endif + +#include "identd.h" +#include "error.h" + +extern void *malloc(); + +/* +** This function will eat whitespace characters until +** either a non-whitespace character is read, or EOF +** occurs. This function is only used if the "-m" option +** is enabled. +*/ +static int eat_whitespace() +{ + int c; + + + while ((c = getchar()) != EOF && + !(c == '\r' || c == '\n')) + ; + + if (c != EOF) + while ((c = getchar()) != EOF && + (c == ' ' || c == '\t' || c == '\n' || c == '\r')) + ; + + if (c != EOF) + ungetc(c, stdin); + + return (c != EOF); +} + + +#ifdef INCLUDE_EXTENSIONS +/* +** Validate an indirect request +*/ +static int valid_fhost(faddr, password) + struct in_addr *faddr; + char *password; +{ + if (indirect_host == NULL) + return 0; + + if (strcmp(indirect_host, "*") != 0) + { + if (isdigit(indirect_host[0])) + { + if (strcmp(inet_ntoa(*faddr), indirect_host)) + { + syslog(LOG_NOTICE, "valid_fhost: access denied for: %s", + gethost(faddr)); + return 0; + } + } + else + { + if (strcmp(gethost(faddr), indirect_host)) + { + syslog(LOG_NOTICE, "valid_fhost: access denied for: %s", + gethost(faddr)); + return 0; + } + } + } + + if (indirect_password == NULL) + return 1; + + if (strcmp(password, indirect_password)) + { + syslog(LOG_NOTICE, "valid_fhost: invalid password from: %s", + gethost(faddr)); + return 0; + } + + return 1; +} +#endif + +/* +** A small routine to check for the existance of the ".noident" +** file in a users home directory. +*/ +static int check_noident(homedir) + char *homedir; +{ + char *tmp_path; + struct stat sbuf; + int rcode; + + + if (!homedir) + return 0; + + tmp_path = (char *) malloc(strlen(homedir) + sizeof("/.noident") + 1); + if (!tmp_path) + return 0; + + strcpy(tmp_path, homedir); + strcat(tmp_path, "/.noident"); + + rcode = stat(tmp_path, &sbuf); + free(tmp_path); + + return (rcode == 0); +} + + +int parse(fp, laddr, faddr) + FILE *fp; + struct in_addr *laddr, *faddr; +{ + int uid, try, rcode; + struct passwd *pwp; + char lhostaddr[16]; + char fhostaddr[16]; + char password[33]; +#ifdef INCLUDE_EXTENSIONS + char arg[33]; + int c; +#endif + struct in_addr laddr2; + struct in_addr faddr2; + + + if (debug_flag && syslog_flag) + syslog(LOG_DEBUG, "In function parse()"); + + /* + ** Get the local/foreign port pair from the luser + */ + do + { + if (debug_flag && syslog_flag) + syslog(LOG_DEBUG, " Before fscanf()"); + + faddr2 = *faddr; + laddr2 = *laddr; + lport = fport = 0; + lhostaddr[0] = fhostaddr[0] = password[0] = '\0'; + + /* Read query from client */ + rcode = fscanf(fp, " %d , %d", &lport, &fport); + +#ifdef INCLUDE_EXTENSIONS + /* + ** Do additional parsing in case of extended request + */ + if (rcode == 0) + { + rcode = fscanf(fp, "%32[^ \t\n\r:]", arg); + + /* Skip leading space up to EOF, EOL or non-space char */ + while ((c = getc(fp)) == ' ' || c == '\t') + ; + + if (rcode <= 0) + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST"); + continue; + } + + /* + ** Non-standard extended request, returns with Pidentd + ** version information + */ + if (strcmp(arg, "VERSION") == 0) + { + printf("%d , %d : ERROR : X-VERSION : %s\r\n", lport, fport, + version); + continue; + } + + /* + ** Non-standard extended proxy request + */ + else if (strcmp(arg, "PROXY") == 0 && c == ':') + { + /* We have a colon char, check for port numbers */ + rcode = fscanf(fp, " %d , %d : %15[0-9.] , %15[0-9.]", + &lport, &fport, fhostaddr, lhostaddr); + + if (!(rcode == 3 || rcode == 4)) + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST"); + continue; + } + + if (rcode == 4) + laddr2.s_addr = inet_addr(lhostaddr); + + faddr2.s_addr = inet_addr(fhostaddr); + + proxy(&laddr2, &faddr2, lport, fport, NULL); + continue; + } + + /* + ** Non-standard extended remote indirect request + */ + else if (strcmp(arg, "REMOTE") == 0 && c == ':') + { + /* We have a colon char, check for port numbers */ + rcode = fscanf(fp, " %d , %d", &lport, &fport); + + /* Skip leading space up to EOF, EOL or non-space char */ + while ((c = getc(fp)) == ' ' || c == '\t') + ; + + if (rcode != 2 || c != ':') + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST"); + continue; + } + + /* We have a colon char, check for addr and password */ + rcode = fscanf(fp, " %15[0-9.] , %32[^ \t\r\n]", + fhostaddr, password); + if (rcode > 0) + rcode += 2; + else + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST"); + continue; + } + + /* + ** Verify that the host originating the indirect request + ** is allowed to do that + */ + if (!valid_fhost(faddr, password)) + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-ACCESS-DENIED"); + continue; + } + + faddr2.s_addr = inet_addr(fhostaddr); + } + + else + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST"); + continue; + } + } +#endif /* EXTENSIONS */ + + if (rcode < 2 || lport < 1 || lport > 65535 || fport < 1 || fport > 65535) + { + if (syslog_flag && rcode > 0) + syslog(LOG_NOTICE, "scanf: invalid-port(s): %d , %d from %s", + lport, fport, gethost(faddr)); + + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "INVALID-PORT"); + continue; + } + + if (syslog_flag && verbose_flag) + syslog(LOG_NOTICE, "request for (%d,%d) from %s", + lport, fport, gethost(faddr)); + + if (debug_flag && syslog_flag) + syslog(LOG_DEBUG, " After fscanf(), before k_getuid()"); + + /* + ** Next - get the specific TCP connection and return the + ** uid - user number. + ** + ** Try to fetch the information 5 times incase the + ** kernel changed beneath us and we missed or took + ** a fault. + */ + for (try = 0; + (try < 5 && + k_getuid(&faddr2, htons(fport), laddr, htons(lport), &uid) == -1); + try++) + ; + + if (try >= 5) + { + if (syslog_flag) + syslog(LOG_DEBUG, "Returned: %d , %d : NO-USER", lport, fport); + + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "NO-USER"); + continue; + } + + if (try > 0 && syslog_flag) + syslog(LOG_NOTICE, "k_getuid retries: %d", try); + + if (debug_flag && syslog_flag) + syslog(LOG_DEBUG, " After k_getuid(), before getpwuid()"); + + /* + ** Then we should try to get the username. If that fails we + ** return it as an OTHER identifier + */ + pwp = getpwuid(uid); + + if (!pwp) + { + if (syslog_flag) + syslog(LOG_WARNING, "getpwuid() could not map uid (%d) to name", + uid); + + printf("%d , %d : USERID : OTHER%s%s : %d\r\n", + lport, fport, + charset_name ? " , " : "", + charset_name ? charset_name : "", + uid); + continue; + } + + /* + ** Hey! We finally made it!!! + */ + if (syslog_flag) + syslog(LOG_DEBUG, "Successful lookup: %d , %d : %s", + lport, fport, pwp->pw_name); + + if (noident_flag && check_noident(pwp->pw_dir)) + { + if (syslog_flag && verbose_flag) + syslog(LOG_NOTICE, "user %s requested HIDDEN-USER for host %s: %d, %d", + pwp->pw_name, + gethost(faddr), + lport, fport); + + printf("%d , %d : ERROR : HIDDEN-USER\r\n", + lport, fport); + continue; + } + + if (number_flag) + printf("%d , %d : USERID : OTHER%s%s : %d\r\n", + lport, fport, + charset_name ? " , " : "", + charset_name ? charset_name : "", + uid); + else + printf("%d , %d : USERID : %s%s%s : %s\r\n", + lport, fport, + other_flag ? "OTHER" : "UNIX", + charset_name ? " , " : "", + charset_name ? charset_name : "", + pwp->pw_name); + + } while(fflush(stdout), fflush(stderr), multi_flag && eat_whitespace()); + + return 0; +} diff --git a/identd.tproj/proxy.c b/identd.tproj/proxy.c new file mode 100644 index 0000000..a64c581 --- /dev/null +++ b/identd.tproj/proxy.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: proxy.c,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ +** +** proxy.c This file implements the proxy() call. +** +** This program is in the public domain and may be used freely by anyone +** who wants to. +** +** Last update: 12 Dec 1992 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#include +#include + +#include "identd.h" + + +#ifdef INCLUDE_PROXY +#include +#include +#include + +#include +#endif + + +/* +** This function should establish a connection to a remote IDENT +** server and query it for the information associated with the +** specified connection and the return that to the caller. +** +** Should there be three different timeouts (Connection Establishment, +** Query Transmit and Query Receive)? +*/ +int proxy(laddr, faddr, lport, fport, timeout) + struct in_addr *laddr; + struct in_addr *faddr; + int lport; + int fport; + struct timeval *timeout; +{ +#ifndef INCLUDE_PROXY + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-NOT-YET-IMPLEMENTED"); + + return -1; +#else + id_t *idp; + char *answer; + char *opsys; + char *charset; + + idp = id_open(laddr, faddr, timeout); + if (!idp) + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-CONNECTION-REFUSED"); + return -1; + } + + if (id_query(idp, lport, fport, timeout) < 0) + { + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-TRANSMIT-QUERY-ERROR"); + id_close(idp); + return -1; + } + + switch (id_parse(idp, timeout, &lport, &fport, &answer, &opsys, &charset)) + { + case 1: + printf("%d , %d : USERID : %s %s%s : %s\r\n", + lport, fport, + opsys, + charset ? "," : "", + charset ? charset : "", + answer); + break; + + case 2: + printf("%d , %d : ERROR : %s\r\n", + lport, fport, answer); + break; + + case 0: /* More to parse - fix this later! */ + case -1: /* Internal error */ + default: + printf("%d , %d : ERROR : %s\r\n", + lport, fport, + unknown_flag ? "UNKNOWN-ERROR" : "X-PARSE-REPLY-ERROR"); + } + + id_close(idp); +#endif +} diff --git a/identd.tproj/version.c b/identd.tproj/version.c new file mode 100644 index 0000000..dbeeab2 --- /dev/null +++ b/identd.tproj/version.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $Id: version.c,v 1.1.1.1 1999/05/02 03:57:41 wsanchez Exp $ */ +char *version = "2.1.2"; diff --git a/identd.tproj/xpaths.h b/identd.tproj/xpaths.h new file mode 100644 index 0000000..df55f1a --- /dev/null +++ b/identd.tproj/xpaths.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* +** $Id: xpaths.h,v 1.1.1.2 2000/01/11 01:48:48 wsanchez Exp $ +** +** paths.h Common path definitions for the in.identd daemon +** +** Last update: 11 Dec 1992 +** +** Please send bug fixes/bug reports to: Peter Eriksson +*/ + +#include + +#ifdef SEQUENT +# define _PATH_UNIX "/dynix" +#endif + +#if defined(MIPS) || defined(IRIX) +# define _PATH_UNIX "/unix" +#endif + +#if defined(hpux) || defined(__hpux) +# define _PATH_UNIX "/hp-ux" +#endif + +#ifdef SOLARIS +# define _PATH_UNIX "/dev/ksyms" +#else +# ifdef SVR4 +# define _PATH_UNIX "/stand/unix" +# endif +#endif + +#ifdef BSD43 +# define _PATH_SWAP "/dev/drum" +# define _PATH_MEM "/dev/mem" +#endif + +#ifdef _AUX_SOURCE +# define _PATH_UNIX "/unix" +#endif + +#ifdef _CRAY +# define _PATH_UNIX "/unicos" +# define _PATH_MEM "/dev/mem" +#endif + +#ifdef __APPLE__ +# define _PATH_UNIX "/mach" +#endif + + +/* + * Some defaults... + */ +#ifndef _PATH_KMEM +# define _PATH_KMEM "/dev/kmem" +#endif + +#ifndef _PATH_UNIX +# define _PATH_UNIX "/vmunix" +#endif + + +#ifndef PATH_CONFIG +# define PATH_CONFIG "/etc/identd.conf" +#endif diff --git a/ifconfig.tproj/Makefile b/ifconfig.tproj/Makefile new file mode 100644 index 0000000..2ae172d --- /dev/null +++ b/ifconfig.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ifconfig + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = ifconfig.h + +CFILES = ifconfig.c ifmedia.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.dist ifconfig.8\ + Makefile.postamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ifconfig.tproj/Makefile.dist b/ifconfig.tproj/Makefile.dist new file mode 100644 index 0000000..8be2193 --- /dev/null +++ b/ifconfig.tproj/Makefile.dist @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= ifconfig +MAN8= ifconfig.0 + +.include diff --git a/ifconfig.tproj/Makefile.postamble b/ifconfig.tproj/Makefile.postamble new file mode 100644 index 0000000..c188e2f --- /dev/null +++ b/ifconfig.tproj/Makefile.postamble @@ -0,0 +1,3 @@ +after_install: + install -d $(DSTROOT)/usr/share/man/man8 + install -c -m 444 ifconfig.8 $(DSTROOT)/usr/share/man/man8 diff --git a/ifconfig.tproj/Makefile.preamble b/ifconfig.tproj/Makefile.preamble new file mode 100644 index 0000000..5a6d897 --- /dev/null +++ b/ifconfig.tproj/Makefile.preamble @@ -0,0 +1,3 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include +OTHER_CFLAGS += -DUSE_IF_MEDIA diff --git a/ifconfig.tproj/PB.project b/ifconfig.tproj/PB.project new file mode 100644 index 0000000..e699c93 --- /dev/null +++ b/ifconfig.tproj/PB.project @@ -0,0 +1,32 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (ifconfig.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (ifconfig.c, ifmedia.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, ifconfig.8, Makefile.postamble); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = ifconfig; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = ifconfig; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ifconfig; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = ifconfig; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ifconfig.tproj/ifconfig.8 b/ifconfig.tproj/ifconfig.8 new file mode 100644 index 0000000..216d66a --- /dev/null +++ b/ifconfig.tproj/ifconfig.8 @@ -0,0 +1,320 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ifconfig.8 8.4 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt IFCONFIG 8 +.Os BSD 4.2 +.Sh NAME +.Nm ifconfig +.Nd configure network interface parameters +.Sh SYNOPSIS +.Nm ifconfig +.Ar interface address_family +.Oo +.Ar address +.Op Ar dest_address +.Oc +.Op Ar parameters +.Nm ifconfig +.Ar interface +.Op Ar protocol_family +.Nm ifconfig +.Fl a +.Op Fl d +.Op Fl u +.Op Ar address_family +.Nm ifconfig +.Fl l +.Op Fl d +.Op Fl u +.Op Ar address_family +.Sh DESCRIPTION +.Nm Ifconfig +is used to assign an address +to a network interface and/or configure +network interface parameters. +.Nm Ifconfig +must be used at boot time to define the network address +of each interface present on a machine; it may also be used at +a later time to redefine an interface's address +or other operating parameters. +.Pp +Available operands for +.Nm ifconfig: +.Bl -tag -width Ds +.It Ar Address +For the +.Tn DARPA-Internet +family, +the address is either a host name present in the host name data +base, +.Xr hosts 5 , +or a +.Tn DARPA +Internet address expressed in the Internet standard +.Dq dot notation . +For the Xerox Network Systems(tm) family, +addresses are +.Ar net:a.b.c.d.e.f , +where +.Ar net +is the assigned network number (in decimal), +and each of the six bytes of the host number, +.Ar a +through +.Ar f , +are specified in hexadecimal. +The host number may be omitted on 10Mb/s Ethernet interfaces, +which use the hardware physical address, +and on interfaces other than the first. +For the +.Tn ISO +family, addresses are specified as a long hexadecimal string, +as in the Xerox family. However, two consecutive dots imply a zero +byte, and the dots are optional, if the user wishes to (carefully) +count out long strings of digits in network byte order. +.It Ar address_family +Specifies the +.Ar address family +which affects interpretation of the remaining parameters. +Since an interface can receive transmissions in differing protocols +with different naming schemes, specifying the address family is recommeded. +The address or protocol families currently +supported are +.Dq inet , +.Dq iso , +and +.Dq ns . +.It Ar Interface +The +.Ar interface +parameter is a string of the form +.Dq name unit , +for example, +.Dq en0 +.El +.Pp +The following parameters may be set with +.Nm ifconfig : +.Bl -tag -width dest_addressxx +.It Cm alias +Establish an additional network address for this interface. This is +sometimes useful when changing network numbers, and one wishes to +accept packets addressed to the old interface. +A +.Ar netmask +should be used with this parameter. +If the new ( +.Ar alias +) address is on the same subnet as an existing address assigned to +this interface, the netmask must be "255.255.255.255". If a netmask +is not supplied, the command will use the one implied by the address +itself (e.g, Class A). If the 'all ones' netmask is used, the system +will handle route installation. If another netmask is used, a route +to that address must be installed by hand, e.g., "route add -host +XX.XX.XX.XX -interface 127.0.0.1", where "XX.XX.XX.XX" is the new +alias (c.f. +.Ar route +(8)). In either case, the administrator may have to remove a route +by hand when the alias is removed ( +.Ar -alias +or +.Ar delete +) +.It Cm arp +Enable the use of the Address Resolution Protocol in mapping +between network level addresses and link level addresses (default). +This is currently implemented for mapping between +.Tn DARPA +Internet +addresses and 10Mb/s Ethernet addresses. +.It Fl arp +Disable the use of the Address Resolution Protocol. +.It Cm broadcast +(Inet only) +Specify the address to use to represent broadcasts to the +network. +The default broadcast address is the address with a host part of all 1's. +.It Cm debug +Enable driver dependent debugging code; usually, this turns on +extra console error logging. +.It Fl debug +Disable driver dependent debugging code. +.ne 1i +.It Cm delete +Remove the network address specified. +This would be used if you incorrectly specified an alias, or it +was no longer needed. +If you have incorrectly set an NS address having the side effect +of specifying the host portion, removing all NS addresses will +allow you to respecify the host portion. +.It Cm dest_address +Specify the address of the correspondent on the other end +of a point to point link. +.It Cm down +Mark an interface ``down''. When an interface is +marked ``down'', the system will not attempt to +transmit messages through that interface. +If possible, the interface will be reset to disable reception as well. +This action does not automatically disable routes using the interface. +.It Cm ipdst +This is used to specify an Internet host who is willing to receive +ip packets encapsulating NS packets bound for a remote network. +An apparent point to point link is constructed, and +the address specified will be taken as the NS address and network +of the destination. +IP encapsulation of +.Tn CLNP +packets is done differently. +.It Cm metric Ar n +Set the routing metric of the interface to +.Ar n , +default 0. +The routing metric is used by the routing protocol +.Pq Xr routed 8 . +Higher metrics have the effect of making a route +less favorable; metrics are counted as addition hops +to the destination network or host. +.It Cm netmask Ar mask +(Inet and ISO) +Specify how much of the address to reserve for subdividing +networks into sub-networks. +The mask includes the network part of the local address +and the subnet part, which is taken from the host field of the address. +The mask can be specified as a single hexadecimal number +with a leading 0x, with a dot-notation Internet address, +or with a pseudo-network name listed in the network table +.Xr networks 5 . +The mask contains 1's for the bit positions in the 32-bit address +which are to be used for the network and subnet parts, +and 0's for the host part. +The mask should contain at least the standard network portion, +and the subnet field should be contiguous with the network +portion. +.\" see +.\" Xr eon 5 . +.It Cm nsellength Ar n +.Pf ( Tn ISO +only) +This specifies a trailing number of bytes for a received +.Tn NSAP +used for local identification, the remaining leading part of which is +taken to be the +.Tn NET +(Network Entity Title). +The default value is 1, which is conformant to US +.Tn GOSIP . +When an ISO address is set in an ifconfig command, +it is really the +.Tn NSAP +which is being specified. +For example, in +.Tn US GOSIP , +20 hex digits should be +specified in the +.Tn ISO NSAP +to be assigned to the interface. +There is some evidence that a number different from 1 may be useful +for +.Tn AFI +37 type addresses. +.It Cm trailers +Request the use of a ``trailer'' link level encapsulation when +sending (default). +If a network interface supports +.Cm trailers , +the system will, when possible, encapsulate outgoing +messages in a manner which minimizes the number of +memory to memory copy operations performed by the receiver. +On networks that support the Address Resolution Protocol (see +.Xr arp 4 ; +currently, only 10 Mb/s Ethernet), +this flag indicates that the system should request that other +systems use trailers when sending to this host. +Similarly, trailer encapsulations will be sent to other +hosts that have made such requests. +Currently used by Internet protocols only. +.It Fl trailers +Disable the use of a ``trailer'' link level encapsulation. +.It Cm link[0-2] +Enable special processing of the link level of the interface. +These three options are interface specific in actual effect, however, +they are in general used to select special modes of operation. An example +of this is to enable SLIP compression. Currently, only used by SLIP. +.ne 1i +.It Fl link[0-2] +Disable special processing at the link level with the specified interface. +.It Cm up +Mark an interface ``up''. +This may be used to enable an interface after an ``ifconfig down.'' +It happens automatically when setting the first address on an interface. +If the interface was reset when previously marked down, +the hardware will be re-initialized. +.El +.Pp +Special flags for +.Nm ifconfig: +.Bl -tag -width Ds +.It -a +Produce a full listing for all available interfaces. +.It -l +Produce a name-only listing for all available interfaces. +.It -d +limit the listing to those interfaces that are down. +.It -u +limit the listing to those interfaces that are up. +.El +.Pp +.Pp +.Nm Ifconfig +displays the current configuration for a network interface +when no optional parameters are supplied. +If a protocol family is specified, +Ifconfig will report only the details specific to that protocol family. +.Pp +Only the super-user may modify the configuration of a network interface. +.Sh DIAGNOSTICS +Messages indicating the specified interface does not exit, the +requested address is unknown, or the user is not privileged and +tried to alter an interface's configuration. +.Sh SEE ALSO +.Xr netstat 1 , +.Xr netintro 4 , +.Xr rc 8 , +.Xr routed 8 , +.\" .Xr eon 5 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/ifconfig.tproj/ifconfig.c b/ifconfig.tproj/ifconfig.c new file mode 100644 index 0000000..0165a69 --- /dev/null +++ b/ifconfig.tproj/ifconfig.c @@ -0,0 +1,870 @@ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94"; +#endif +static const char rcsid[] = + "$Id: ifconfig.c,v 1.1.1.2 2000/01/11 01:48:49 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* IP */ +#include +#include +#include +#include + +/* OSI */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ifconfig.h" + +struct ifreq ifr, ridreq; +struct ifaliasreq addreq; +struct sockaddr_in netmask; + + +char name[32]; +int flags; +int metric; +int mtu; +int setaddr; +int setipdst; +int doalias; +int clearaddr; +int newaddr = 1; + +struct afswtch; + +void Perror __P((const char *cmd)); + +int ifconfig __P((int argc, char *const *argv, const struct afswtch *afp)); +void notealias __P((const char *, int, int, const struct afswtch *afp)); +void printb __P((const char *s, unsigned value, const char *bits)); +void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); +void status __P((const struct afswtch *afp, int addrcount, + struct sockaddr_dl *sdl, struct if_msghdr *ifm, + struct ifa_msghdr *ifam)); +void usage __P((void)); + +typedef void c_func __P((const char *cmd, int arg, int s, const struct afswtch *afp)); + +c_func setifaddr, setifbroadaddr, setifdstaddr, setifnetmask; +c_func setifipdst; +c_func setifflags, setifmetric, setifmtu; + + +#define NEXTARG 0xffffff + +const +struct cmd { + const char *c_name; + int c_parameter; /* NEXTARG means next argv */ + void (*c_func) __P((const char *, int, int, const struct afswtch *afp)); +} cmds[] = { + { "up", IFF_UP, setifflags } , + { "down", -IFF_UP, setifflags }, + { "arp", -IFF_NOARP, setifflags }, + { "-arp", IFF_NOARP, setifflags }, + { "debug", IFF_DEBUG, setifflags }, + { "-debug", -IFF_DEBUG, setifflags }, + { "alias", IFF_UP, notealias }, + { "-alias", -IFF_UP, notealias }, + { "delete", -IFF_UP, notealias }, +#ifdef notdef +#define EN_SWABIPS 0x1000 + { "swabips", EN_SWABIPS, setifflags }, + { "-swabips", -EN_SWABIPS, setifflags }, +#endif + { "netmask", NEXTARG, setifnetmask }, + { "range", NEXTARG, 0 }, + { "phase", NEXTARG, 0 }, + { "metric", NEXTARG, setifmetric }, + { "broadcast", NEXTARG, setifbroadaddr }, + { "ipdst", NEXTARG, setifipdst }, + { "link0", IFF_LINK0, setifflags }, + { "-link0", -IFF_LINK0, setifflags }, + { "link1", IFF_LINK1, setifflags }, + { "-link1", -IFF_LINK1, setifflags }, + { "link2", IFF_LINK2, setifflags }, + { "-link2", -IFF_LINK2, setifflags }, +#if USE_IF_MEDIA + { "media", NEXTARG, setmedia }, + { "mediaopt", NEXTARG, setmediaopt }, + { "-mediaopt", NEXTARG, unsetmediaopt }, +#endif + { "normal", -IFF_LINK0, setifflags }, + { "compress", IFF_LINK0, setifflags }, + { "noicmp", IFF_LINK1, setifflags }, + { "mtu", NEXTARG, setifmtu }, + { 0, 0, setifaddr }, + { 0, 0, setifdstaddr }, +}; + +/* + * XNS support liberally adapted from code written at the University of + * Maryland principally by James O'Toole and Chris Torek. + */ +typedef void af_status __P((int, struct rt_addrinfo *)); +typedef void af_getaddr __P((const char *, int)); + +af_status in_status, ipx_status, at_status, ether_status; +af_getaddr in_getaddr, ipx_getaddr, at_getaddr; + +/* Known address families */ +const +struct afswtch { + const char *af_name; + short af_af; + af_status *af_status; + af_getaddr *af_getaddr; + u_long af_difaddr; + u_long af_aifaddr; + caddr_t af_ridreq; + caddr_t af_addreq; +} afs[] = { +#define C(x) ((caddr_t) &x) + { "inet", AF_INET, in_status, in_getaddr, + SIOCDIFADDR, SIOCAIFADDR, C(ridreq), C(addreq) }, + { "ether", AF_INET, ether_status, NULL }, /* XXX not real!! */ +#if 0 /* XXX conflicts with the media command */ +#if USE_IF_MEDIA + { "media", AF_INET, media_status, NULL }, /* XXX not real!! */ +#endif +#endif + { 0, 0, 0, 0 } +}; + +/* + * Expand the compacted form of addresses as returned via the + * configuration read via sysctl(). + */ + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +void +rt_xaddrs(cp, cplim, rtinfo) + caddr_t cp, cplim; + struct rt_addrinfo *rtinfo; +{ + struct sockaddr *sa; + int i; + + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + + +void +usage() +{ + fprintf(stderr, "%s\n%s\n%s\n%s\n", + "usage: ifconfig interface address_family [address [dest_address]]", + " [parameters]", + " ifconfig -a [-d] [-u] [address_family]", + " ifconfig -l [-d] [-u] [address_family]"); + exit(1); +} + +int +main(argc, argv) + int argc; + char *const *argv; +{ + int c; + int all, namesonly, downonly, uponly; + int foundit = 0, need_nl = 0; + const struct afswtch *afp = 0; + int addrcount; + struct if_msghdr *ifm, *nextifm; + struct ifa_msghdr *ifam; + struct sockaddr_dl *sdl; + char *buf, *lim, *next; + + + size_t needed; + int mib[6]; + + /* Parse leading line options */ + all = downonly = uponly = namesonly = 0; + while ((c = getopt(argc, argv, "adlmu")) != -1) { + switch (c) { + case 'a': /* scan all interfaces */ + all++; + break; + case 'l': /* scan interface names only */ + namesonly++; + break; + case 'd': /* restrict scan to "down" interfaces */ + downonly++; + break; + case 'u': /* restrict scan to "up" interfaces */ + uponly++; + break; + case 'm': /* show media choices in status */ + /* ignored for compatibility */ + break; + default: + usage(); + break; + } + } + argc -= optind; + argv += optind; + + /* -l cannot be used with -a or -m */ + if (namesonly && all) + usage(); + + /* nonsense.. */ + if (uponly && downonly) + usage(); + + /* -a and -l allow an address family arg to limit the output */ + if (all || namesonly) { + if (argc > 1) + usage(); + + if (argc == 1) { + for (afp = afs; afp->af_name; afp++) + if (strcmp(afp->af_name, *argv) == 0) { + argc--, argv++; + break; + } + if (afp->af_name == NULL) + usage(); + /* leave with afp non-zero */ + } + } else { + /* not listing, need an argument */ + if (argc < 1) + usage(); + + strncpy(name, *argv, sizeof(name)); + argc--, argv++; + } + + /* Check for address family */ + if (argc > 0) { + for (afp = afs; afp->af_name; afp++) + if (strcmp(afp->af_name, *argv) == 0) { + argc--, argv++; + break; + } + if (afp->af_name == NULL) + afp = NULL; /* not a family, NULL */ + } + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; /* address family */ + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + + /* if particular family specified, only ask about it */ + if (afp) + mib[3] = afp->af_af; + + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + errx(1, "iflist-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + errx(1, "malloc"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + errx(1, "actual retrieval of interface table"); + lim = buf + needed; + + next = buf; + while (next < lim) { + + ifm = (struct if_msghdr *)next; + + if (ifm->ifm_type == RTM_IFINFO) { + sdl = (struct sockaddr_dl *)(ifm + 1); + flags = ifm->ifm_flags; + } else { + fprintf(stderr, "out of sync parsing NET_RT_IFLIST\n"); + fprintf(stderr, "expected %d, got %d\n", RTM_IFINFO, + ifm->ifm_type); + fprintf(stderr, "msglen = %d\n", ifm->ifm_msglen); + fprintf(stderr, "buf:%p, next:%p, lim:%p\n", buf, next, + lim); + exit (1); + } + + next += ifm->ifm_msglen; + ifam = NULL; + addrcount = 0; + while (next < lim) { + + nextifm = (struct if_msghdr *)next; + + if (nextifm->ifm_type != RTM_NEWADDR) + break; + + if (ifam == NULL) + ifam = (struct ifa_msghdr *)nextifm; + + addrcount++; + next += nextifm->ifm_msglen; + } + + if (all || namesonly) { + if (uponly) + if ((flags & IFF_UP) == 0) + continue; /* not up */ + if (downonly) + if (flags & IFF_UP) + continue; /* not down */ + strncpy(name, sdl->sdl_data, sdl->sdl_nlen); + name[sdl->sdl_nlen] = '\0'; + if (namesonly) { + if (afp == NULL || + afp->af_status != ether_status || + sdl->sdl_type == IFT_ETHER) { + if (need_nl) + putchar(' '); + fputs(name, stdout); + need_nl++; + } + continue; + } + } else { + if (strlen(name) != sdl->sdl_nlen) + continue; /* not same len */ + if (strncmp(name, sdl->sdl_data, sdl->sdl_nlen) != 0) + continue; /* not same name */ + } + + if (argc > 0) + ifconfig(argc, argv, afp); + else + status(afp, addrcount, sdl, ifm, ifam); + + if (all == 0 && namesonly == 0) { + foundit++; /* flag it as 'done' */ + break; + } + } + free(buf); + + if (namesonly && need_nl > 0) + putchar('\n'); + + if (all == 0 && namesonly == 0 && foundit == 0) + errx(1, "interface %s does not exist", name); + + + exit (0); +} + + +int +ifconfig(argc, argv, afp) + int argc; + char *const *argv; + const struct afswtch *afp; +{ + int s; + + if (afp == NULL) + afp = &afs[0]; + ifr.ifr_addr.sa_family = afp->af_af; + strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + + if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) + err(1, "socket"); + + while (argc > 0) { + register const struct cmd *p; + + for (p = cmds; p->c_name; p++) + if (strcmp(*argv, p->c_name) == 0) + break; + if (p->c_name == 0 && setaddr) + p++; /* got src, do dst */ + if (p->c_func) { + if (p->c_parameter == NEXTARG) { + if (argv[1] == NULL) + errx(1, "'%s' requires argument", + p->c_name); + (*p->c_func)(argv[1], 0, s, afp); + argc--, argv++; + } else + (*p->c_func)(*argv, p->c_parameter, s, afp); + } + argc--, argv++; + } + + if (clearaddr) { + if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { + warnx("interface %s cannot change %s addresses!", + name, afp->af_name); + clearaddr = NULL; + } + } + if (clearaddr) { + int ret; + strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name); + if ((ret = ioctl(s, afp->af_difaddr, afp->af_ridreq)) < 0) { + if (errno == EADDRNOTAVAIL && (doalias >= 0)) { + /* means no previous address for interface */ + } else + Perror("ioctl (SIOCDIFADDR)"); + } + } + if (newaddr) { + if (afp->af_ridreq == NULL || afp->af_difaddr == 0) { + warnx("interface %s cannot change %s addresses!", + name, afp->af_name); + newaddr = NULL; + } + } + if (newaddr) { + strncpy(afp->af_addreq, name, sizeof ifr.ifr_name); + if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0) + Perror("ioctl (SIOCAIFADDR)"); + } + close(s); + return(0); +} +#define RIDADDR 0 +#define ADDR 1 +#define MASK 2 +#define DSTADDR 3 + +/*ARGSUSED*/ +void +setifaddr(addr, param, s, afp) + const char *addr; + int param; + int s; + const struct afswtch *afp; +{ + /* + * Delay the ioctl to set the interface addr until flags are all set. + * The address interpretation may depend on the flags, + * and the flags may change when the address is set. + */ + setaddr++; + if (doalias == 0) + clearaddr = 1; + (*afp->af_getaddr)(addr, (doalias >= 0 ? ADDR : RIDADDR)); +} + +void +setifnetmask(addr, dummy, s, afp) + const char *addr; + int dummy ; + int s; + const struct afswtch *afp; +{ + (*afp->af_getaddr)(addr, MASK); +} + +void +setifbroadaddr(addr, dummy, s, afp) + const char *addr; + int dummy ; + int s; + const struct afswtch *afp; +{ + (*afp->af_getaddr)(addr, DSTADDR); +} + +void +setifipdst(addr, dummy, s, afp) + const char *addr; + int dummy ; + int s; + const struct afswtch *afp; +{ + in_getaddr(addr, DSTADDR); + setipdst++; + clearaddr = 0; + newaddr = 0; +} +#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr)) + +void +notealias(addr, param, s, afp) + const char *addr; + int param; + int s; + const struct afswtch *afp; +{ + if (setaddr && doalias == 0 && param < 0) + bcopy((caddr_t)rqtosa(af_addreq), + (caddr_t)rqtosa(af_ridreq), + rqtosa(af_addreq)->sa_len); + doalias = param; + if (param < 0) { + clearaddr = 1; + newaddr = 0; + } else + clearaddr = 0; +} + +/*ARGSUSED*/ +void +setifdstaddr(addr, param, s, afp) + const char *addr; + int param ; + int s; + const struct afswtch *afp; +{ + (*afp->af_getaddr)(addr, DSTADDR); +} + +void +setifflags(vname, value, s, afp) + const char *vname; + int value; + int s; + const struct afswtch *afp; +{ + if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&ifr) < 0) { + Perror("ioctl (SIOCGIFFLAGS)"); + exit(1); + } + strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + flags = ifr.ifr_flags; + + if (value < 0) { + value = -value; + flags &= ~value; + } else + flags |= value; + ifr.ifr_flags = flags; + if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&ifr) < 0) + Perror(vname); +} + +void +setifmetric(val, dummy, s, afp) + const char *val; + int dummy ; + int s; + const struct afswtch *afp; +{ + strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + ifr.ifr_metric = atoi(val); + if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0) + warn("ioctl (set metric)"); +} + +void +setifmtu(val, dummy, s, afp) + const char *val; + int dummy ; + int s; + const struct afswtch *afp; +{ + strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name)); + ifr.ifr_mtu = atoi(val); + if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0) + warn("ioctl (set mtu)"); +} + + +#define IFFBITS \ +"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6b6\7RUNNING" \ +"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \ +"\20MULTICAST" + +/* + * Print the status of the interface. If an address family was + * specified, show it and it only; otherwise, show them all. + */ +void +status(afp, addrcount, sdl, ifm, ifam) + const struct afswtch *afp; + int addrcount; + struct sockaddr_dl *sdl; + struct if_msghdr *ifm; + struct ifa_msghdr *ifam; +{ + const struct afswtch *p = NULL; + struct rt_addrinfo info; + int allfamilies, s; + + if (afp == NULL) { + allfamilies = 1; + afp = &afs[0]; + } else + allfamilies = 0; + + ifr.ifr_addr.sa_family = afp->af_af; + strncpy(ifr.ifr_name, name, sizeof ifr.ifr_name); + + if ((s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0)) < 0) + err(1, "socket"); + + /* + * XXX is it we are doing a SIOCGIFMETRIC etc for one family. + * is it possible that the metric and mtu can be different for + * each family? If so, we have a format problem, because the + * metric and mtu is printed on the global the flags line. + */ + if (ioctl(s, SIOCGIFMETRIC, (caddr_t)&ifr) < 0) + warn("ioctl (SIOCGIFMETRIC)"); + else + metric = ifr.ifr_metric; + + if (ioctl(s, SIOCGIFMTU, (caddr_t)&ifr) < 0) + warn("ioctl (SIOCGIFMTU)"); + else + mtu = ifr.ifr_mtu; + + printf("%s: ", name); + printb("flags", flags, IFFBITS); + if (metric) + printf(" metric %d", metric); + if (mtu) + printf(" mtu %d", mtu); + putchar('\n'); + + while (addrcount > 0) { + + info.rti_addrs = ifam->ifam_addrs; + + /* Expand the compacted addresses */ + rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, + &info); + + if (!allfamilies) { + if (afp->af_af == info.rti_info[RTAX_IFA]->sa_family && +#if USE_IF_MEDIA + afp->af_status != media_status && +#endif + afp->af_status != ether_status) { + p = afp; + (*p->af_status)(s, &info); + } + } else for (p = afs; p->af_name; p++) { + if (p->af_af == info.rti_info[RTAX_IFA]->sa_family && +#if USE_IF_MEDIA + p->af_status != media_status && +#endif + p->af_status != ether_status) + (*p->af_status)(s, &info); + } + addrcount--; + ifam = (struct ifa_msghdr *)((char *)ifam + ifam->ifam_msglen); + } + if (allfamilies || afp->af_status == ether_status) + ether_status(s, (struct rt_addrinfo *)sdl); +#if USE_IF_MEDIA + if (allfamilies || afp->af_status == media_status) + media_status(s, NULL); +#endif + if (!allfamilies && !p && + afp->af_status != ether_status) + warnx("%s has no %s interface address!", name, afp->af_name); + + close(s); + return; +} + +void +in_status(s, info) + int s ; + struct rt_addrinfo * info; +{ + struct sockaddr_in *sin, null_sin; + + memset(&null_sin, 0, sizeof(null_sin)); + + sin = (struct sockaddr_in *)info->rti_info[RTAX_IFA]; + printf("\tinet %s ", inet_ntoa(sin->sin_addr)); + + if (flags & IFF_POINTOPOINT) { + /* note RTAX_BRD overlap with IFF_BROADCAST */ + sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; + if (!sin) + sin = &null_sin; + printf("--> %s ", inet_ntoa(sin->sin_addr)); + } + + sin = (struct sockaddr_in *)info->rti_info[RTAX_NETMASK]; + if (!sin) + sin = &null_sin; + printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr)); + + if (flags & IFF_BROADCAST) { + /* note RTAX_BRD overlap with IFF_POINTOPOINT */ + sin = (struct sockaddr_in *)info->rti_info[RTAX_BRD]; + if (sin && sin->sin_addr.s_addr != 0) + printf("broadcast %s", inet_ntoa(sin->sin_addr)); + } + putchar('\n'); +} + +void +ether_status(s, info) + int s ; + struct rt_addrinfo *info; +{ + char *cp; + int n; + struct sockaddr_dl *sdl = (struct sockaddr_dl *)info; + + cp = (char *)LLADDR(sdl); + if ((n = sdl->sdl_alen) > 0) { + if (sdl->sdl_type == IFT_ETHER) + printf ("\tether "); + else + printf ("\tlladdr "); + while (--n >= 0) + printf("%02x%c",*cp++ & 0xff, n>0? ':' : ' '); + putchar('\n'); + } +} + +void +Perror(cmd) + const char *cmd; +{ + switch (errno) { + + case ENXIO: + errx(1, "%s: no such interface", cmd); + break; + + case EPERM: + errx(1, "%s: permission denied", cmd); + break; + + default: + err(1, "%s", cmd); + } +} + +#define SIN(x) ((struct sockaddr_in *) &(x)) +struct sockaddr_in *sintab[] = { +SIN(ridreq.ifr_addr), SIN(addreq.ifra_addr), +SIN(addreq.ifra_mask), SIN(addreq.ifra_broadaddr)}; + +void +in_getaddr(s, which) + const char *s; + int which; +{ + register struct sockaddr_in *sin = sintab[which]; + struct hostent *hp; + struct netent *np; + + sin->sin_len = sizeof(*sin); + if (which != MASK) + sin->sin_family = AF_INET; + + if (inet_aton(s, &sin->sin_addr)) + return; + if ((hp = gethostbyname(s)) != 0) + bcopy(hp->h_addr, (char *)&sin->sin_addr, + MIN(hp->h_length, sizeof(sin->sin_addr))); + else if ((np = getnetbyname(s)) != 0) + sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY); + else + errx(1, "%s: bad value", s); +} + +/* + * Print a value a la the %b format of the kernel's printf + */ +void +printb(s, v, bits) + const char *s; + register unsigned v; + register const char *bits; +{ + register int i, any = 0; + register char c; + + if (bits && *bits == 8) + printf("%s=%o", s, v); + else + printf("%s=%x", s, v); + bits++; + if (bits) { + putchar('<'); + while ((i = *bits++) != '\0') { + if (v & (1 << (i-1))) { + if (any) + putchar(','); + any = 1; + for (; (c = *bits) > 32; bits++) + putchar(c); + } else + for (; *bits > 32; bits++) + ; + } + putchar('>'); + } +} + + diff --git a/ifconfig.tproj/ifconfig.h b/ifconfig.tproj/ifconfig.h new file mode 100644 index 0000000..a088b7a --- /dev/null +++ b/ifconfig.tproj/ifconfig.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997 Peter Wemm. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the FreeBSD Project + * by Peter Wemm. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * so there! + * + * $Id: ifconfig.h,v 1.1.1.1 2000/01/11 01:48:49 wsanchez Exp $ + */ + +extern struct ifreq ifr; + +extern char name[32]; /* name of interface */ +extern int allmedia; +struct afswtch; + +extern void setmedia(const char *, int, int, const struct afswtch *rafp); +extern void setmediaopt(const char *, int, int, const struct afswtch *rafp); +extern void unsetmediaopt(const char *, int, int, const struct afswtch *rafp); +extern void media_status(int s, struct rt_addrinfo *); diff --git a/ifconfig.tproj/ifmedia.c b/ifconfig.tproj/ifmedia.c new file mode 100644 index 0000000..1657c21 --- /dev/null +++ b/ifconfig.tproj/ifmedia.c @@ -0,0 +1,554 @@ +/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */ +/* $FreeBSD: src/sbin/ifconfig/ifmedia.c,v 1.6 1999/08/28 00:13:08 peter Exp $ */ + +/* + * Copyright (c) 1997 Jason R. Thorpe. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project + * by Jason R. Thorpe. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ifconfig.h" + +static void domediaopt __P((const char *, int, int)); +static int get_media_subtype __P((int, const char *)); +static int get_media_options __P((int, const char *)); +static int lookup_media_word __P((struct ifmedia_description *, const char *)); +static void print_media_word __P((int)); + +void +media_status(s, info) + int s; + struct rt_addrinfo *info; +{ + struct ifmediareq ifmr; + int *media_list, i; + + (void) memset(&ifmr, 0, sizeof(ifmr)); + (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); + + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { + /* + * Interface doesn't support SIOC{G,S}IFMEDIA. + */ + return; + } + + if (ifmr.ifm_count == 0) { + //warnx("%s: no media types?", name); + return; + } + + media_list = (int *)malloc(ifmr.ifm_count * sizeof(int)); + if (media_list == NULL) + err(1, "malloc"); + ifmr.ifm_ulist = media_list; + + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + err(1, "SIOCGIFMEDIA"); + + printf("\tmedia: "); + print_media_word(ifmr.ifm_current); + if (ifmr.ifm_active != ifmr.ifm_current) { + putchar(' '); + putchar('('); + print_media_word(ifmr.ifm_active); + putchar(')'); + } + + if (ifmr.ifm_status & IFM_AVALID) { + printf(" status: "); +#if 0 + switch (IFM_TYPE(ifmr.ifm_active)) { + case IFM_ETHER: + if (ifmr.ifm_status & IFM_ACTIVE) + printf("active"); + else + printf("no carrier"); + break; + + case IFM_FDDI: + case IFM_TOKEN: + if (ifmr.ifm_status & IFM_ACTIVE) + printf("inserted"); + else + printf("no ring"); + break; + } +#endif 0 + if (ifmr.ifm_status & IFM_ACTIVE) + printf("active"); + else + printf("inactive"); + } + + putchar('\n'); + + if (ifmr.ifm_count > 0) { + printf("\tsupported media:"); + for (i = 0; i < ifmr.ifm_count; i++) { + putchar(' '); + print_media_word(media_list[i]); + } + putchar('\n'); + } + + free(media_list); +} + +void +setmedia(val, d, s, afp) + const char *val; + int d; + int s; + const struct afswtch *afp; +{ + struct ifmediareq ifmr; + int first_type, subtype; + + (void) memset(&ifmr, 0, sizeof(ifmr)); + (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); + + ifmr.ifm_count = 1; + ifmr.ifm_ulist = &first_type; + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { + /* + * If we get E2BIG, the kernel is telling us + * that there are more, so we can ignore it. + */ + if (errno != E2BIG) + err(1, "SIOCGIFMEDIA"); + } + + if (ifmr.ifm_count == 0) + errx(1, "%s: no media types?", name); + + /* + * We are primarily concerned with the top-level type. + * However, "current" may be only IFM_NONE, so we just look + * for the top-level type in the first "supported type" + * entry. + * + * (I'm assuming that all supported media types for a given + * interface will be the same top-level type..) + */ + subtype = get_media_subtype(IFM_TYPE(first_type), val); + + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_media = (ifmr.ifm_current & ~(IFM_NMASK|IFM_TMASK)) | + IFM_TYPE(first_type) | subtype; + + if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) + err(1, "SIOCSIFMEDIA"); +} + +void +setmediaopt(val, d, s, afp) + const char *val; + int d; + int s; + const struct afswtch *afp; +{ + + domediaopt(val, 0, s); +} + +void +unsetmediaopt(val, d, s, afp) + const char *val; + int d; + int s; + const struct afswtch *afp; +{ + + domediaopt(val, 1, s); +} + +static void +domediaopt(val, clear, s) + const char *val; + int clear; + int s; +{ + struct ifmediareq ifmr; + int *mwords, options; + + (void) memset(&ifmr, 0, sizeof(ifmr)); + (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name)); + + /* + * We must go through the motions of reading all + * supported media because we need to know both + * the current media type and the top-level type. + */ + + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + err(1, "SIOCGIFMEDIA"); + + if (ifmr.ifm_count == 0) + errx(1, "%s: no media types?", name); + + mwords = (int *)malloc(ifmr.ifm_count * sizeof(int)); + if (mwords == NULL) + err(1, "malloc"); + + ifmr.ifm_ulist = mwords; + if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) + err(1, "SIOCGIFMEDIA"); + + options = get_media_options(IFM_TYPE(mwords[0]), val); + + free(mwords); + + strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); + ifr.ifr_media = ifmr.ifm_current; + if (clear) + ifr.ifr_media &= ~options; + else + ifr.ifr_media |= options; + + if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0) + err(1, "SIOCSIFMEDIA"); +} + +/********************************************************************** + * A good chunk of this is duplicated from sys/net/ifmedia.c + **********************************************************************/ + +static struct ifmedia_description ifm_type_descriptions[] = + IFM_TYPE_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_ethernet_descriptions[] = + IFM_SUBTYPE_ETHERNET_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_ethernet_aliases[] = + IFM_SUBTYPE_ETHERNET_ALIASES; + +static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] = + IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_tokenring_descriptions[] = + IFM_SUBTYPE_TOKENRING_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_tokenring_aliases[] = + IFM_SUBTYPE_TOKENRING_ALIASES; + +static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] = + IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_fddi_descriptions[] = + IFM_SUBTYPE_FDDI_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_fddi_aliases[] = + IFM_SUBTYPE_FDDI_ALIASES; + +static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] = + IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] = + IFM_SUBTYPE_IEEE80211_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] = + IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_shared_descriptions[] = + IFM_SUBTYPE_SHARED_DESCRIPTIONS; + +static struct ifmedia_description ifm_subtype_shared_aliases[] = + IFM_SUBTYPE_SHARED_ALIASES; + +static struct ifmedia_description ifm_shared_option_descriptions[] = + IFM_SHARED_OPTION_DESCRIPTIONS; + +struct ifmedia_type_to_subtype { + struct { + struct ifmedia_description *desc; + int alias; + } subtypes[5]; + struct { + struct ifmedia_description *desc; + int alias; + } options[3]; +}; + +/* must be in the same order as IFM_TYPE_DESCRIPTIONS */ +static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = { + { + { + { &ifm_subtype_shared_descriptions[0], 0 }, + { &ifm_subtype_shared_aliases[0], 1 }, + { &ifm_subtype_ethernet_descriptions[0], 0 }, + { &ifm_subtype_ethernet_aliases[0], 1 }, + { NULL, 0 }, + }, + { + { &ifm_shared_option_descriptions[0], 0 }, + { &ifm_subtype_ethernet_option_descriptions[0], 1 }, + { NULL, 0 }, + }, + }, + { + { + { &ifm_subtype_shared_descriptions[0], 0 }, + { &ifm_subtype_shared_aliases[0], 1 }, + { &ifm_subtype_tokenring_descriptions[0], 0 }, + { &ifm_subtype_tokenring_aliases[0], 1 }, + { NULL, 0 }, + }, + { + { &ifm_shared_option_descriptions[0], 0 }, + { &ifm_subtype_tokenring_option_descriptions[0], 1 }, + { NULL, 0 }, + }, + }, + { + { + { &ifm_subtype_shared_descriptions[0], 0 }, + { &ifm_subtype_shared_aliases[0], 1 }, + { &ifm_subtype_fddi_descriptions[0], 0 }, + { &ifm_subtype_fddi_aliases[0], 1 }, + { NULL, 0 }, + }, + { + { &ifm_shared_option_descriptions[0], 0 }, + { &ifm_subtype_fddi_option_descriptions[0], 1 }, + { NULL, 0 }, + }, + }, + { + { + { &ifm_subtype_shared_descriptions[0], 0 }, + { &ifm_subtype_shared_aliases[0], 1 }, + { &ifm_subtype_ieee80211_descriptions[0], 0 }, + { NULL, 0 }, + }, + { + { &ifm_shared_option_descriptions[0], 0 }, + { &ifm_subtype_ieee80211_option_descriptions[0], 1 }, + { NULL, 0 }, + }, + }, +}; + +static int +get_media_subtype(type, val) + int type; + const char *val; +{ + struct ifmedia_description *desc; + struct ifmedia_type_to_subtype *ttos; + int rval, i; + + /* Find the top-level interface type. */ + for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; + desc->ifmt_string != NULL; desc++, ttos++) + if (type == desc->ifmt_word) + break; + if (desc->ifmt_string == NULL) + errx(1, "unknown media type 0x%x", type); + + for (i = 0; ttos->subtypes[i].desc != NULL; i++) { + rval = lookup_media_word(ttos->subtypes[i].desc, val); + if (rval != -1) + return (rval); + } + errx(1, "unknown media subtype: %s", val); + /* NOTREACHED */ +} + +static int +get_media_options(type, val) + int type; + const char *val; +{ + struct ifmedia_description *desc; + struct ifmedia_type_to_subtype *ttos; + char *optlist, *optptr; + int option = 0, i, rval = 0; + + /* We muck with the string, so copy it. */ + optlist = strdup(val); + if (optlist == NULL) + err(1, "strdup"); + + /* Find the top-level interface type. */ + for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; + desc->ifmt_string != NULL; desc++, ttos++) + if (type == desc->ifmt_word) + break; + if (desc->ifmt_string == NULL) + errx(1, "unknown media type 0x%x", type); + + /* + * Look up the options in the user-provided comma-separated + * list. + */ + optptr = optlist; + for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) { + for (i = 0; ttos->options[i].desc != NULL; i++) { + option = lookup_media_word(ttos->options[i].desc, optptr); + if (option != -1) + break; + } + if (option == 0) + errx(1, "unknown option: %s", optptr); + rval |= option; + } + + free(optlist); + return (rval); +} + +static int +lookup_media_word(desc, val) + struct ifmedia_description *desc; + const char *val; +{ + + for (; desc->ifmt_string != NULL; desc++) + if (strcasecmp(desc->ifmt_string, val) == 0) + return (desc->ifmt_word); + + return (-1); +} + +static void +print_media_word(ifmw) + int ifmw; +{ + struct ifmedia_description *desc; + struct ifmedia_type_to_subtype *ttos; + int seen_option = 0, i; + + /* Find the top-level interface type. */ + for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes; + desc->ifmt_string != NULL; desc++, ttos++) + if (IFM_TYPE(ifmw) == desc->ifmt_word) + break; + if (desc->ifmt_string == NULL) { + printf(""); + return; + } + + /* + * Don't print the top-level type; it's not like we can + * change it, or anything. + */ + + /* Find subtype. */ + for (i = 0; ttos->subtypes[i].desc != NULL; i++) { + if (ttos->subtypes[i].alias) + continue; + for (desc = ttos->subtypes[i].desc; + desc->ifmt_string != NULL; desc++) { + if (IFM_SUBTYPE(ifmw) == desc->ifmt_word) + goto got_subtype; + } + } + + /* Falling to here means unknown subtype. */ + printf(""); + return; + + got_subtype: + printf("%s", desc->ifmt_string); + + /* Find options. */ + for (i = 0; ttos->options[i].desc != NULL; i++) { + if (ttos->options[i].alias) + continue; + for (desc = ttos->options[i].desc; + desc->ifmt_string != NULL; desc++) { + if (ifmw & desc->ifmt_word) { + if (seen_option == 0) + printf(" <"); + printf("%s%s", seen_option++ ? "," : "", + desc->ifmt_string); + } + } + } + printf("%s", seen_option ? ">" : ""); +} + +/********************************************************************** + * ...until here. + **********************************************************************/ diff --git a/inetd.tproj/Makefile b/inetd.tproj/Makefile new file mode 100644 index 0000000..bd27a46 --- /dev/null +++ b/inetd.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = inetd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = pathnames.h + +CFILES = inetd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble inetd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/inetd.tproj/Makefile.postamble b/inetd.tproj/Makefile.postamble new file mode 100644 index 0000000..f5c79e2 --- /dev/null +++ b/inetd.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/inetd.tproj/Makefile.preamble b/inetd.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/inetd.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/inetd.tproj/PB.project b/inetd.tproj/PB.project new file mode 100644 index 0000000..2eafcda --- /dev/null +++ b/inetd.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (pathnames.h); + OTHER_LIBS = (); + OTHER_LINKED = (inetd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, inetd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = inetd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/inetd.tproj/inetd.8 b/inetd.tproj/inetd.8 new file mode 100644 index 0000000..cc11efe --- /dev/null +++ b/inetd.tproj/inetd.8 @@ -0,0 +1,381 @@ +.\" Copyright (c) 1985, 1991, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)inetd.8 8.4 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt INETD 8 +.Os BSD 4.4 +.Sh NAME +.Nm inetd +.Nd internet +.Dq super-server +.Sh SYNOPSIS +.Nm inetd +.Op Fl d +.Op Fl R Ar rate +.Op Ar configuration file +.Sh DESCRIPTION +The +.Nm inetd +program +should be run at boot time by +.Pa /etc/rc +(see +.Xr rc 8 ) . +It then listens for connections on certain +internet sockets. When a connection is found on one +of its sockets, it decides what service the socket +corresponds to, and invokes a program to service the request. +The server program is invoked with the service socket +as its standard input, output and error descriptors. +After the program is +finished, +.Nm inetd +continues to listen on the socket (except in some cases which +will be described below). Essentially, +.Nm inetd +allows running one daemon to invoke several others, +reducing load on the system. +.Pp +The options available for +.Nm inetd: +.Bl -tag -width Ds +.It Fl d +Turns on debugging. +.It Fl R Ar rate +Specifies the maximum number of times a service can be invoked +in one minute; the default is 1000. +.El +.Pp +Upon execution, +.Nm inetd +reads its configuration information from a configuration +file which, by default, is +.Pa /etc/inetd.conf . +There must be an entry for each field of the configuration +file, with entries for each field separated by a tab or +a space. Comments are denoted by a ``#'' at the beginning +of a line. There must be an entry for each field. The +fields of the configuration file are as follows: +.Pp +.Bd -unfilled -offset indent -compact +service name +socket type +protocol +wait/nowait +user +server program +server program arguments +.Ed +.Pp +There are two types of services that +.Nm inetd +can start: standard and TCPMUX. +A standard service has a well-known port assigned to it; +it may be a service that implements an official Internet standard or is a +BSD-specific service. +As described in +.Tn RFC 1078 , +TCPMUX services are nonstandard services that do not have a +well-known port assigned to them. +They are invoked from +.Nm inetd +when a program connects to the +.Dq tcpmux +well-known port and specifies +the service name. +This feature is useful for adding locally-developed servers. +.Pp +The +.Em service-name +entry is the name of a valid service in +the file +.Pa /etc/services . +For +.Dq internal +services (discussed below), the service +name +.Em must +be the official name of the service (that is, the first entry in +.Pa /etc/services ) . +For TCPMUX services, the value of the +.Em service-name +field consists of the string +.Dq tcpmux +followed by a slash and the +locally-chosen service name. +The service names listed in +.Pa /etc/services +and the name +.Dq help +are reserved. +Try to choose unique names for your TCPMUX services by prefixing them with +your organization's name and suffixing them with a version number. +.Pp +The +.Em socket-type +should be one of +.Dq stream , +.Dq dgram , +.Dq raw , +.Dq rdm , +or +.Dq seqpacket , +depending on whether the socket is a stream, datagram, raw, +reliably delivered message, or sequenced packet socket. +TCPMUX services must use +.Dq stream . +.Pp +The +.Em protocol +must be a valid protocol as given in +.Pa /etc/protocols . +Examples might be +.Dq tcp +or +.Dq udp . +TCPMUX services must use +.Dq tcp . +.Pp +The +.Em wait/nowait +entry specifies whether the server that is invoked by inetd will take over +the socket associated with the service access point, and thus whether +.Nm inetd +should wait for the server to exit before listening for new service +requests. +Datagram servers must use +.Dq wait , +as they are always invoked with the original datagram socket bound +to the specified service address. +These servers must read at least one datagram from the socket +before exiting. +If a datagram server connects +to its peer, freeing the socket so +.Nm inetd +can received further messages on the socket, it is said to be +a +.Dq multi-threaded +server; +it should read one datagram from the socket and create a new socket +connected to the peer. +It should fork, and the parent should then exit +to allow +.Nm inetd +to check for new service requests to spawn new servers. +Datagram servers which process all incoming datagrams +on a socket and eventually time out are said to be +.Dq single-threaded . +.Xr Comsat 8 , +.Pq Xr biff 1 +and +.Xr talkd 8 +are both examples of the latter type of +datagram server. +.Xr Tftpd 8 +is an example of a multi-threaded datagram server. +.Pp +Servers using stream sockets generally are multi-threaded and +use the +.Dq nowait +entry. +Connection requests for these services are accepted by +.Nm inetd , +and the server is given only the newly-accepted socket connected +to a client of the service. +Most stream-based services operate in this manner. +Stream-based servers that use +.Dq wait +are started with the listening service socket, and must accept +at least one connection request before exiting. +Such a server would normally accept and process incoming connection +requests until a timeout. +TCPMUX services must use +.Dq nowait . +.Pp +The +.Em user +entry should contain the user name of the user as whom the server +should run. This allows for servers to be given less permission +than root. +.Pp +The +.Em server-program +entry should contain the pathname of the program which is to be +executed by +.Nm inetd +when a request is found on its socket. If +.Nm inetd +provides this service internally, this entry should +be +.Dq internal . +.Pp +The +.Em server program arguments +should be just as arguments +normally are, starting with argv[0], which is the name of +the program. If the service is provided internally, the +word +.Dq internal +should take the place of this entry. +.Pp +The +.Nm inetd +program +provides several +.Dq trivial +services internally by use of +routines within itself. These services are +.Dq echo , +.Dq discard , +.Dq chargen +(character generator), +.Dq daytime +(human readable time), and +.Dq time +(machine readable time, +in the form of the number of seconds since midnight, January +1, 1900). All of these services are tcp based. For +details of these services, consult the appropriate +.Tn RFC +from the Network Information Center. +.Pp +The +.Nm inetd +program +rereads its configuration file when it receives a hangup signal, +.Dv SIGHUP . +Services may be added, deleted or modified when the configuration file +is reread. +Except when started in debugging mode, +.Nm +records its process ID in the file +.Pa /var/run/inetd.pid +to assist in reconfiguration. +.Sh TCPMUX +.Pp +.Tn RFC 1078 +describes the TCPMUX protocol: +``A TCP client connects to a foreign host on TCP port 1. It sends the +service name followed by a carriage-return line-feed . The +service name is never case sensitive. The server replies with a +single character indicating positive (+) or negative (\-) +acknowledgment, immediately followed by an optional message of +explanation, terminated with a . If the reply was positive, +the selected protocol begins; otherwise the connection is closed.'' +The program is passed the TCP connection as file descriptors 0 and 1. +.Pp +If the TCPMUX service name begins with a ``+'', +.Nm inetd +returns the positive reply for the program. +This allows you to invoke programs that use stdin/stdout +without putting any special server code in them. +.Pp +The special service name +.Dq help +causes +.Nm inetd +to list TCPMUX services in +.Pa inetd.conf . +.ne 1i +.Sh "EXAMPLES" +.Pp +Here are several example service entries for the various types of services: +.Bd -literal +ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l +ntalk dgram udp wait root /usr/libexec/ntalkd ntalkd +tcpmux/+date stream tcp nowait guest /bin/date date +tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook +.Ed +.Sh "ERROR MESSAGES" +The +.Nm inetd +server +logs error messages using +.Xr syslog 3 . +Important error messages and their explanations are: +.Bd -literal +\fIservice\fP/\fIprotocol\fP server failing (looping), service terminated. +.Ed +The number of requests for the specified service in the past minute +exceeded the limit. The limit exists to prevent a broken program +or a malicious user from swamping the system. +This message may occur for several reasons: +1) there are lots of hosts requesting the service within a short time period, +2) a 'broken' client program is requesting the service too frequently, +3) a malicious user is running a program to invoke the service in +a 'denial of service' attack, or +4) the invoked service program has an error that causes clients +to retry quickly. +Use the +.Op Fl R +option, +as described above, to change the rate limit. +Once the limit is reached, the service will be +reenabled automatically in 10 minutes. +.sp +.Bd -literal +\fIservice\fP/\fIprotocol\fP: No such user '\fIuser\fP', service ignored +\fIservice\fP/\fIprotocol\fP: getpwnam: \fIuser\fP: No such user +.Ed +No entry for +.Em user +exists in the +.Pa passwd +file. The first message +occurs when +.Nm inetd +(re)reads the configuration file. The second message occurs when the +service is invoked. +.sp +.Bd -literal +\fIservice\fP: can't set uid \fInumber\fP +\fIservice\fP: can't set gid \fInumber\fP +.Ed +The user or group ID for the entry's +.Em user +is invalid. +.Sh SEE ALSO +.Xr comsat 8 , +.Xr fingerd 8 , +.Xr ftpd 8 , +.Xr rexecd 8 , +.Xr rlogind 8 , +.Xr rshd 8 , +.Xr telnetd 8 , +.Xr tftpd 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . +TCPMUX is based on code and documentation by Mark Lottor. diff --git a/inetd.tproj/inetd.c b/inetd.tproj/inetd.c new file mode 100644 index 0000000..1b93a68 --- /dev/null +++ b/inetd.tproj/inetd.c @@ -0,0 +1,1293 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; +#endif /* not lint */ + +/* + * Inetd - Internet super-server + * + * This program invokes all internet services as needed. Connection-oriented + * services are invoked each time a connection is made, by creating a process. + * This process is passed the connection as file descriptor 0 and is expected + * to do a getpeername to find out the source host and port. + * + * Datagram oriented services are invoked when a datagram + * arrives; a process is created and passed a pending message + * on file descriptor 0. Datagram servers may either connect + * to their peer, freeing up the original socket for inetd + * to receive further messages on, or ``take over the socket'', + * processing all arriving datagrams and, eventually, timing + * out. The first type of server is said to be ``multi-threaded''; + * the second type of server ``single-threaded''. + * + * Inetd uses a configuration file which is read at startup + * and, possibly, at some later time in response to a hangup signal. + * The configuration file is ``free format'' with fields given in the + * order shown below. Continuation lines for an entry must being with + * a space or tab. All fields must be present in each entry. + * + * service name must be in /etc/services or must + * name a tcpmux service + * socket type stream/dgram/raw/rdm/seqpacket + * protocol must be in /etc/protocols + * wait/nowait single-threaded/multi-threaded + * user user to run daemon as + * server program full path name + * server program arguments maximum of MAXARGS (20) + * + * TCP services without official port numbers are handled with the + * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for + * requests. When a connection is made from a foreign host, the service + * requested is passed to tcpmux, which looks it up in the servtab list + * and returns the proper entry for the service. Tcpmux returns a + * negative reply if the service doesn't exist, otherwise the invoked + * server is expected to return the positive reply if the service type in + * inetd.conf file has the prefix "tcpmux/". If the service type has the + * prefix "tcpmux/+", tcpmux will return the positive reply for the + * process; this is for compatibility with older server code, and also + * allows you to invoke programs that use stdin/stdout without putting any + * special server code in them. Services that use tcpmux are "nowait" + * because they do not have a well-known port and hence cannot listen + * for new requests. + * + * Comment lines are indicated by a `#' in column 1. + */ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pathnames.h" + +#define TOOMANY 100 /* don't start more than TOOMANY */ +#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ +#define RETRYTIME (60*10) /* retry after bind or server fail */ + +#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) + + +int debug = 0; +int nsock, maxsock; +fd_set allsock; +int options; +int timingout; +int toomany = TOOMANY; +struct servent *sp; + +struct servtab { + char *se_service; /* name of service */ + int se_socktype; /* type of socket to use */ + char *se_proto; /* protocol used */ + short se_wait; /* single threaded server */ + short se_checked; /* looked at during merge */ + char *se_user; /* user name to run as */ + struct biltin *se_bi; /* if built-in, description */ + char *se_server; /* server program */ +#define MAXARGV 20 + char *se_argv[MAXARGV+1]; /* program arguments */ + int se_fd; /* open descriptor */ + int se_type; /* type */ + struct sockaddr_in se_ctrladdr;/* bound address */ + int se_count; /* number started since se_time */ + struct timeval se_time; /* start of se_count */ + struct servtab *se_next; +} *servtab; + +#define NORM_TYPE 0 +#define MUX_TYPE 1 +#define MUXPLUS_TYPE 2 +#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ + ((sep)->se_type == MUXPLUS_TYPE)) +#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) + + +void chargen_dg __P((int, struct servtab *)); +void chargen_stream __P((int, struct servtab *)); +void close_sep __P((struct servtab *)); +void config __P((int)); +void daytime_dg __P((int, struct servtab *)); +void daytime_stream __P((int, struct servtab *)); +void discard_dg __P((int, struct servtab *)); +void discard_stream __P((int, struct servtab *)); +void echo_dg __P((int, struct servtab *)); +void echo_stream __P((int, struct servtab *)); +void endconfig __P((void)); +struct servtab *enter __P((struct servtab *)); +void freeconfig __P((struct servtab *)); +struct servtab *getconfigent __P((void)); +void machtime_dg __P((int, struct servtab *)); +void machtime_stream __P((int, struct servtab *)); +char *newstr __P((char *)); +char *nextline __P((FILE *)); +void print_service __P((char *, struct servtab *)); +void reapchild __P((int)); +void retry __P((int)); +int setconfig __P((void)); +void setup __P((struct servtab *)); +char *sskip __P((char **)); +char *skip __P((char **)); +struct servtab *tcpmux __P((int)); + +struct biltin { + char *bi_service; /* internally provided service name */ + int bi_socktype; /* type of socket supported */ + short bi_fork; /* 1 if should fork before call */ + short bi_wait; /* 1 if should wait for child */ + void (*bi_fn)(); /* function which performs it */ +} biltins[] = { + /* Echo received data */ + { "echo", SOCK_STREAM, 1, 0, echo_stream }, + { "echo", SOCK_DGRAM, 0, 0, echo_dg }, + + /* Internet /dev/null */ + { "discard", SOCK_STREAM, 1, 0, discard_stream }, + { "discard", SOCK_DGRAM, 0, 0, discard_dg }, + + /* Return 32 bit time since 1970 */ + { "time", SOCK_STREAM, 0, 0, machtime_stream }, + { "time", SOCK_DGRAM, 0, 0, machtime_dg }, + + /* Return human-readable time */ + { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, + { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, + + /* Familiar character generator */ + { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, + { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, + + { "tcpmux", SOCK_STREAM, 1, 0, (void (*)())tcpmux }, + + { NULL } +}; + +#define NUMINT (sizeof(intab) / sizeof(struct inent)) +char *CONFIG = _PATH_INETDCONF; +char *pid_file = _PATH_INETDPID; +char **Argv; +char *LastArg; + +int +main(argc, argv, envp) + int argc; + char *argv[], *envp[]; +{ + struct servtab *sep; + struct passwd *pwd; + struct sigvec sv; + int tmpint, ch, dofork; + pid_t pid; + char buf[50]; + + Argv = argv; + if (envp == 0 || *envp == 0) + envp = argv; + while (*envp) + envp++; + LastArg = envp[-1] + strlen(envp[-1]); + + openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); + + while ((ch = getopt(argc, argv, "dR:p:")) != EOF) + switch(ch) { + case 'd': + debug = 1; + options |= SO_DEBUG; + break; + case 'R': { /* invocation rate */ + char *p; + + tmpint = strtol(optarg, &p, 0); + if (tmpint < 1 || *p) + syslog(LOG_ERR, + "-R %s: bad value for service invocation rate", + optarg); + else + toomany = tmpint; + break; + } + case 'p': + pid_file = optarg; + break; + case '?': + default: + syslog(LOG_ERR, + "usage: inetd [-d] [-R rate] [conf-file]"); + exit(1); + } + argc -= optind; + argv += optind; + + if (argc > 0) + CONFIG = argv[0]; + if (debug == 0) { + FILE *fp; + daemon(0, 0); + + pid = getpid(); + fp = fopen(pid_file, "w"); + if( fp ) { + fprintf(fp, "%ld\n", (long)pid); + fclose(fp); + } else { + syslog(LOG_WARNING, "%s: %m", pid_file); + } + } + memset(&sv, 0, sizeof(sv)); + sv.sv_mask = SIGBLOCK; + sv.sv_handler = retry; + sigvec(SIGALRM, &sv, (struct sigvec *)0); + config(SIGHUP); + sv.sv_handler = config; + sigvec(SIGHUP, &sv, (struct sigvec *)0); + sv.sv_handler = reapchild; + sigvec(SIGCHLD, &sv, (struct sigvec *)0); + + { + /* space for daemons to overwrite environment for ps */ +#define DUMMYSIZE 100 + char dummy[DUMMYSIZE]; + + (void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1); + dummy[DUMMYSIZE - 1] = '\0'; + (void)setenv("inetd_dummy", dummy, 1); + } + + for (;;) { + int n, ctrl; + fd_set readable; + + if (nsock == 0) { + (void) sigblock(SIGBLOCK); + while (nsock == 0) + sigpause(0L); + (void) sigsetmask(0L); + } + readable = allsock; + if ((n = select(maxsock + 1, &readable, (fd_set *)0, + (fd_set *)0, (struct timeval *)0)) <= 0) { + if (n < 0 && errno != EINTR) { + syslog(LOG_WARNING, "select: %m"); + sleep(1); + } + continue; + } + for (sep = servtab; n && sep; sep = sep->se_next) + if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { + n--; + if (debug) + fprintf(stderr, "someone wants %s\n", + sep->se_service); + if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { + ctrl = accept(sep->se_fd, (struct sockaddr *)0, + (int *)0); + if (debug) + fprintf(stderr, "accept, ctrl %d\n", ctrl); + if (ctrl < 0) { + if (errno != EINTR) + syslog(LOG_WARNING, + "accept (for %s): %m", + sep->se_service); + continue; + } + /* + * Call tcpmux to find the real service to exec. + */ + if (sep->se_bi && + sep->se_bi->bi_fn == (void (*)()) tcpmux) { + sep = tcpmux(ctrl); + if (sep == NULL) { + close(ctrl); + continue; + } + } + } else + ctrl = sep->se_fd; + (void) sigblock(SIGBLOCK); + pid = 0; + dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); + if (dofork) { + if (sep->se_count++ == 0) + (void)gettimeofday(&sep->se_time, + (struct timezone *)0); + else if (sep->se_count >= toomany) { + struct timeval now; + + (void)gettimeofday(&now, (struct timezone *)0); + if (now.tv_sec - sep->se_time.tv_sec > + CNT_INTVL) { + sep->se_time = now; + sep->se_count = 1; + } else { + syslog(LOG_ERR, + "%s/%s server failing (looping), service terminated", + sep->se_service, sep->se_proto); + close_sep(sep); + sigsetmask(0L); + if (!timingout) { + timingout = 1; + alarm(RETRYTIME); + } + continue; + } + } + pid = fork(); + } + if (pid < 0) { + syslog(LOG_ERR, "fork: %m"); + if (!sep->se_wait && + sep->se_socktype == SOCK_STREAM) + close(ctrl); + sigsetmask(0L); + sleep(1); + continue; + } + if (pid && sep->se_wait) { + sep->se_wait = pid; + if (sep->se_fd >= 0) { + FD_CLR(sep->se_fd, &allsock); + nsock--; + } + } + sigsetmask(0L); + if (pid == 0) { + if (debug && dofork) + setsid(); + if (dofork) { + if (debug) + fprintf(stderr, "+ Closing from %d\n", + maxsock); + for (tmpint = maxsock; tmpint > 2; tmpint--) + if (tmpint != ctrl) + close(tmpint); + } + if (sep->se_bi) + (*sep->se_bi->bi_fn)(ctrl, sep); + else { + if (debug) + fprintf(stderr, "%d execl %s\n", + getpid(), sep->se_server); + dup2(ctrl, 0); + close(ctrl); + dup2(0, 1); + dup2(0, 2); + if ((pwd = getpwnam(sep->se_user)) == NULL) { + syslog(LOG_ERR, + "%s/%s: %s: No such user", + sep->se_service, sep->se_proto, + sep->se_user); + if (sep->se_socktype != SOCK_STREAM) + recv(0, buf, sizeof (buf), 0); + _exit(1); + } + if (pwd->pw_uid) { + if (setgid(pwd->pw_gid) < 0) { + syslog(LOG_ERR, + "%s: can't set gid %d: %m", + sep->se_service, pwd->pw_gid); + _exit(1); + } + (void) initgroups(pwd->pw_name, + pwd->pw_gid); + if (setuid(pwd->pw_uid) < 0) { + syslog(LOG_ERR, + "%s: can't set uid %d: %m", + sep->se_service, pwd->pw_uid); + _exit(1); + } + } + execv(sep->se_server, sep->se_argv); + if (sep->se_socktype != SOCK_STREAM) + recv(0, buf, sizeof (buf), 0); + syslog(LOG_ERR, + "cannot execute %s: %m", sep->se_server); + _exit(1); + } + } + if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) + close(ctrl); + } + } +} + +void +reapchild(signo) + int signo; +{ + int status; + pid_t pid; + struct servtab *sep; + + for (;;) { + pid = wait3(&status, WNOHANG, (struct rusage *)0); + if (pid <= 0) + break; + if (debug) + fprintf(stderr, "%d reaped, status %#x\n", + pid, status); + for (sep = servtab; sep; sep = sep->se_next) + if (sep->se_wait == pid) { + if (status) + syslog(LOG_WARNING, + "%s: exit status 0x%x", + sep->se_server, status); + if (debug) + fprintf(stderr, "restored %s, fd %d\n", + sep->se_service, sep->se_fd); + FD_SET(sep->se_fd, &allsock); + nsock++; + sep->se_wait = 1; + } + } +} + +void +config(signo) + int signo; +{ + struct servtab *sep, *cp, **sepp; + struct passwd *pwd; + long omask; + + if (!setconfig()) { + syslog(LOG_ERR, "%s: %m", CONFIG); + return; + } + for (sep = servtab; sep; sep = sep->se_next) + sep->se_checked = 0; + while (cp = getconfigent()) { + if ((pwd = getpwnam(cp->se_user)) == NULL) { + syslog(LOG_ERR, + "%s/%s: No such user '%s', service ignored", + cp->se_service, cp->se_proto, cp->se_user); + continue; + } + for (sep = servtab; sep; sep = sep->se_next) + if (strcmp(sep->se_service, cp->se_service) == 0 && + strcmp(sep->se_proto, cp->se_proto) == 0) + break; + if (sep != 0) { + int i; + + omask = sigblock(SIGBLOCK); + /* + * sep->se_wait may be holding the pid of a daemon + * that we're waiting for. If so, don't overwrite + * it unless the config file explicitly says don't + * wait. + */ + if (cp->se_bi == 0 && + (sep->se_wait == 1 || cp->se_wait == 0)) + sep->se_wait = cp->se_wait; +#define SWAP(a, b) { char *c = a; a = b; b = c; } + if (cp->se_user) + SWAP(sep->se_user, cp->se_user); + if (cp->se_server) + SWAP(sep->se_server, cp->se_server); + for (i = 0; i < MAXARGV; i++) + SWAP(sep->se_argv[i], cp->se_argv[i]); + sigsetmask(omask); + freeconfig(cp); + if (debug) + print_service("REDO", sep); + } else { + sep = enter(cp); + if (debug) + print_service("ADD ", sep); + } + sep->se_checked = 1; + if (ISMUX(sep)) { + sep->se_fd = -1; + continue; + } + sp = getservbyname(sep->se_service, sep->se_proto); + if (sp == 0) { + syslog(LOG_ERR, "%s/%s: unknown service", + sep->se_service, sep->se_proto); + sep->se_checked = 0; + continue; + } + if (sp->s_port != sep->se_ctrladdr.sin_port) { + sep->se_ctrladdr.sin_family = AF_INET; + sep->se_ctrladdr.sin_port = sp->s_port; + if (sep->se_fd >= 0) + close_sep(sep); + } + if (sep->se_fd == -1) + setup(sep); + } + endconfig(); + /* + * Purge anything not looked at above. + */ + omask = sigblock(SIGBLOCK); + sepp = &servtab; + while (sep = *sepp) { + if (sep->se_checked) { + sepp = &sep->se_next; + continue; + } + *sepp = sep->se_next; + if (sep->se_fd >= 0) + close_sep(sep); + if (debug) + print_service("FREE", sep); + freeconfig(sep); + free((char *)sep); + } + (void) sigsetmask(omask); +} + +void +retry(signo) + int signo; +{ + struct servtab *sep; + + timingout = 0; + for (sep = servtab; sep; sep = sep->se_next) + if (sep->se_fd == -1) + setup(sep); +} + +void +setup(sep) + struct servtab *sep; +{ + int on = 1; + + if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) { + if (debug) + fprintf(stderr, "socket failed on %s/%s: %s\n", + sep->se_service, sep->se_proto, + strerror(errno)); + syslog(LOG_ERR, "%s/%s: socket: %m", + sep->se_service, sep->se_proto); + return; + } +#define turnon(fd, opt) \ +setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) + if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && + turnon(sep->se_fd, SO_DEBUG) < 0) + syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); + if (turnon(sep->se_fd, SO_REUSEADDR) < 0) + syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); +#undef turnon + if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, + sizeof (sep->se_ctrladdr)) < 0) { + if (debug) + fprintf(stderr, "bind failed on %s/%s: %s\n", + sep->se_service, sep->se_proto, + strerror(errno)); + syslog(LOG_ERR, "%s/%s: bind: %m", + sep->se_service, sep->se_proto); + (void) close(sep->se_fd); + sep->se_fd = -1; + if (!timingout) { + timingout = 1; + alarm(RETRYTIME); + } + return; + } + if (sep->se_socktype == SOCK_STREAM) + listen(sep->se_fd, 10); + FD_SET(sep->se_fd, &allsock); + nsock++; + if (sep->se_fd > maxsock) + maxsock = sep->se_fd; + if (debug) { + fprintf(stderr, "registered %s on %d\n", + sep->se_server, sep->se_fd); + } +} + +/* + * Finish with a service and its socket. + */ +void +close_sep(sep) + struct servtab *sep; +{ + if (sep->se_fd >= 0) { + nsock--; + FD_CLR(sep->se_fd, &allsock); + (void) close(sep->se_fd); + sep->se_fd = -1; + } + sep->se_count = 0; + /* + * Don't keep the pid of this running deamon: when reapchild() + * reaps this pid, it would erroneously increment nsock. + */ + if (sep->se_wait > 1) + sep->se_wait = 1; +} + +struct servtab * +enter(cp) + struct servtab *cp; +{ + struct servtab *sep; + long omask; + + sep = (struct servtab *)malloc(sizeof (*sep)); + if (sep == (struct servtab *)0) { + syslog(LOG_ERR, "Out of memory."); + exit(-1); + } + *sep = *cp; + sep->se_fd = -1; + omask = sigblock(SIGBLOCK); + sep->se_next = servtab; + servtab = sep; + sigsetmask(omask); + return (sep); +} + +FILE *fconfig = NULL; +struct servtab serv; +char line[LINE_MAX]; + +int +setconfig() +{ + + if (fconfig != NULL) { + fseek(fconfig, 0L, SEEK_SET); + return (1); + } + fconfig = fopen(CONFIG, "r"); + return (fconfig != NULL); +} + +void +endconfig() +{ + if (fconfig) { + (void) fclose(fconfig); + fconfig = NULL; + } +} + +struct servtab * +getconfigent() +{ + struct servtab *sep = &serv; + int argc; + char *cp, *arg; + static char TCPMUX_TOKEN[] = "tcpmux/"; +#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) + +more: + while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) + ; + if (cp == NULL) + return ((struct servtab *)0); + /* + * clear the static buffer, since some fields (se_ctrladdr, + * for example) don't get initialized here. + */ + memset((caddr_t)sep, 0, sizeof *sep); + arg = skip(&cp); + if (cp == NULL) { + /* got an empty line containing just blanks/tabs. */ + goto more; + } + if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { + char *c = arg + MUX_LEN; + if (*c == '+') { + sep->se_type = MUXPLUS_TYPE; + c++; + } else + sep->se_type = MUX_TYPE; + sep->se_service = newstr(c); + } else { + sep->se_service = newstr(arg); + sep->se_type = NORM_TYPE; + } + arg = sskip(&cp); + if (strcmp(arg, "stream") == 0) + sep->se_socktype = SOCK_STREAM; + else if (strcmp(arg, "dgram") == 0) + sep->se_socktype = SOCK_DGRAM; + else if (strcmp(arg, "rdm") == 0) + sep->se_socktype = SOCK_RDM; + else if (strcmp(arg, "seqpacket") == 0) + sep->se_socktype = SOCK_SEQPACKET; + else if (strcmp(arg, "raw") == 0) + sep->se_socktype = SOCK_RAW; + else + sep->se_socktype = -1; + sep->se_proto = newstr(sskip(&cp)); + arg = sskip(&cp); + sep->se_wait = strcmp(arg, "wait") == 0; + if (ISMUX(sep)) { + /* + * Silently enforce "nowait" for TCPMUX services since + * they don't have an assigned port to listen on. + */ + sep->se_wait = 0; + + if (strcmp(sep->se_proto, "tcp")) { + syslog(LOG_ERR, + "%s: bad protocol for tcpmux service %s", + CONFIG, sep->se_service); + goto more; + } + if (sep->se_socktype != SOCK_STREAM) { + syslog(LOG_ERR, + "%s: bad socket type for tcpmux service %s", + CONFIG, sep->se_service); + goto more; + } + } + sep->se_user = newstr(sskip(&cp)); + sep->se_server = newstr(sskip(&cp)); + if (strcmp(sep->se_server, "internal") == 0) { + struct biltin *bi; + + for (bi = biltins; bi->bi_service; bi++) + if (bi->bi_socktype == sep->se_socktype && + strcmp(bi->bi_service, sep->se_service) == 0) + break; + if (bi->bi_service == 0) { + syslog(LOG_ERR, "internal service %s unknown", + sep->se_service); + goto more; + } + sep->se_bi = bi; + sep->se_wait = bi->bi_wait; + } else + sep->se_bi = NULL; + argc = 0; + for (arg = skip(&cp); cp; arg = skip(&cp)) + if (argc < MAXARGV) + sep->se_argv[argc++] = newstr(arg); + while (argc <= MAXARGV) + sep->se_argv[argc++] = NULL; + return (sep); +} + +void +freeconfig(cp) + struct servtab *cp; +{ + int i; + + if (cp->se_service) + free(cp->se_service); + if (cp->se_proto) + free(cp->se_proto); + if (cp->se_user) + free(cp->se_user); + if (cp->se_server) + free(cp->se_server); + for (i = 0; i < MAXARGV; i++) + if (cp->se_argv[i]) + free(cp->se_argv[i]); +} + + +/* + * Safe skip - if skip returns null, log a syntax error in the + * configuration file and exit. + */ +char * +sskip(cpp) + char **cpp; +{ + char *cp; + + cp = skip(cpp); + if (cp == NULL) { + syslog(LOG_ERR, "%s: syntax error", CONFIG); + exit(-1); + } + return (cp); +} + +char * +skip(cpp) + char **cpp; +{ + char *cp = *cpp; + char *start; + +again: + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0') { + int c; + + c = getc(fconfig); + (void) ungetc(c, fconfig); + if (c == ' ' || c == '\t') + if (cp = nextline(fconfig)) + goto again; + *cpp = (char *)0; + return ((char *)0); + } + start = cp; + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + if (*cp != '\0') + *cp++ = '\0'; + *cpp = cp; + return (start); +} + +char * +nextline(fd) + FILE *fd; +{ + char *cp; + + if (fgets(line, sizeof (line), fd) == NULL) + return ((char *)0); + cp = strchr(line, '\n'); + if (cp) + *cp = '\0'; + return (line); +} + +char * +newstr(cp) + char *cp; +{ + if (cp = strdup(cp ? cp : "")) + return (cp); + syslog(LOG_ERR, "strdup: %m"); + exit(-1); +} + +void +setproctitle(a, s) + char *a; + int s; +{ + int size; + char *cp; + struct sockaddr_in sin; + char buf[80]; + + cp = Argv[0]; + size = sizeof(sin); + if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) + (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); + else + (void) sprintf(buf, "-%s", a); + strncpy(cp, buf, LastArg - cp); + cp += strlen(cp); + while (cp < LastArg) + *cp++ = ' '; +} + +/* + * Internet services provided internally by inetd: + */ +#define BUFSIZE 8192 + +/* ARGSUSED */ +void +echo_stream(s, sep) /* Echo service -- echo data back */ + int s; + struct servtab *sep; +{ + char buffer[BUFSIZE]; + int i; + + setproctitle(sep->se_service, s); + while ((i = read(s, buffer, sizeof(buffer))) > 0 && + write(s, buffer, i) > 0) + ; + exit(0); +} + +/* ARGSUSED */ +void +echo_dg(s, sep) /* Echo service -- echo data back */ + int s; + struct servtab *sep; +{ + char buffer[BUFSIZE]; + int i, size; + struct sockaddr sa; + + size = sizeof(sa); + if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) + return; + (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); +} + +/* ARGSUSED */ +void +discard_stream(s, sep) /* Discard service -- ignore data */ + int s; + struct servtab *sep; +{ + int ret; + char buffer[BUFSIZE]; + + setproctitle(sep->se_service, s); + while (1) { + while ((ret = read(s, buffer, sizeof(buffer))) > 0) + ; + if (ret == 0 || errno != EINTR) + break; + } + exit(0); +} + +/* ARGSUSED */ +void +discard_dg(s, sep) /* Discard service -- ignore data */ + int s; + struct servtab *sep; +{ + char buffer[BUFSIZE]; + + (void) read(s, buffer, sizeof(buffer)); +} + +#include +#define LINESIZ 72 +char ring[128]; +char *endring; + +void +initring() +{ + int i; + + endring = ring; + + for (i = 0; i <= 128; ++i) + if (isprint(i)) + *endring++ = i; +} + +/* ARGSUSED */ +void +chargen_stream(s, sep) /* Character generator */ + int s; + struct servtab *sep; +{ + int len; + char *rs, text[LINESIZ+2]; + + setproctitle(sep->se_service, s); + + if (!endring) { + initring(); + rs = ring; + } + + text[LINESIZ] = '\r'; + text[LINESIZ + 1] = '\n'; + for (rs = ring;;) { + if ((len = endring - rs) >= LINESIZ) + memmove(text, rs, LINESIZ); + else { + memmove(text, rs, len); + memmove(text + len, ring, LINESIZ - len); + } + if (++rs == endring) + rs = ring; + if (write(s, text, sizeof(text)) != sizeof(text)) + break; + } + exit(0); +} + +/* ARGSUSED */ +void +chargen_dg(s, sep) /* Character generator */ + int s; + struct servtab *sep; +{ + struct sockaddr sa; + static char *rs; + int len, size; + char text[LINESIZ+2]; + + if (endring == 0) { + initring(); + rs = ring; + } + + size = sizeof(sa); + if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) + return; + + if ((len = endring - rs) >= LINESIZ) + memmove(text, rs, LINESIZ); + else { + memmove(text, rs, len); + memmove(text + len, ring, LINESIZ - len); + } + if (++rs == endring) + rs = ring; + text[LINESIZ] = '\r'; + text[LINESIZ + 1] = '\n'; + (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); +} + +/* + * Return a machine readable date and time, in the form of the + * number of seconds since midnight, Jan 1, 1900. Since gettimeofday + * returns the number of seconds since midnight, Jan 1, 1970, + * we must add 2208988800 seconds to this figure to make up for + * some seventy years Bell Labs was asleep. + */ + +long +machtime() +{ + struct timeval tv; + + if (gettimeofday(&tv, (struct timezone *)0) < 0) { + if (debug) + fprintf(stderr, "Unable to get time of day\n"); + return (0L); + } +#define OFFSET ((u_long)25567 * 24*60*60) + return (htonl((long)(tv.tv_sec + OFFSET))); +#undef OFFSET +} + +/* ARGSUSED */ +void +machtime_stream(s, sep) + int s; + struct servtab *sep; +{ + long result; + + result = machtime(); + (void) write(s, (char *) &result, sizeof(result)); +} + +/* ARGSUSED */ +void +machtime_dg(s, sep) + int s; + struct servtab *sep; +{ + long result; + struct sockaddr sa; + int size; + + size = sizeof(sa); + if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) + return; + result = machtime(); + (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); +} + +/* ARGSUSED */ +void +daytime_stream(s, sep) /* Return human-readable time of day */ + int s; + struct servtab *sep; +{ + char buffer[256]; + time_t clock; + + clock = time((time_t *) 0); + + (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); + (void) write(s, buffer, strlen(buffer)); +} + +/* ARGSUSED */ +void +daytime_dg(s, sep) /* Return human-readable time of day */ + int s; + struct servtab *sep; +{ + char buffer[256]; + time_t clock; + struct sockaddr sa; + int size; + + clock = time((time_t *) 0); + + size = sizeof(sa); + if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) + return; + (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); + (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); +} + +/* + * print_service: + * Dump relevant information to stderr + */ +void +print_service(action, sep) + char *action; + struct servtab *sep; +{ + fprintf(stderr, + "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", + action, sep->se_service, sep->se_proto, + sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server); +} + +/* + * Based on TCPMUX.C by Mark K. Lottor November 1988 + * sri-nic::ps:tcpmux.c + */ + + +static int /* # of characters upto \r,\n or \0 */ +getline(fd, buf, len) + int fd; + char *buf; + int len; +{ + int count = 0, n; + + do { + n = read(fd, buf, len-count); + if (n == 0) + return (count); + if (n < 0) + return (-1); + while (--n >= 0) { + if (*buf == '\r' || *buf == '\n' || *buf == '\0') + return (count); + count++; + buf++; + } + } while (count < len); + return (count); +} + +#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ + +#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) + +struct servtab * +tcpmux(s) + int s; +{ + struct servtab *sep; + char service[MAX_SERV_LEN+1]; + int len; + + /* Get requested service name */ + if ((len = getline(s, service, MAX_SERV_LEN)) < 0) { + strwrite(s, "-Error reading service name\r\n"); + return (NULL); + } + service[len] = '\0'; + + if (debug) + fprintf(stderr, "tcpmux: someone wants %s\n", service); + + /* + * Help is a required command, and lists available services, + * one per line. + */ + if (!strcasecmp(service, "help")) { + for (sep = servtab; sep; sep = sep->se_next) { + if (!ISMUX(sep)) + continue; + (void)write(s,sep->se_service,strlen(sep->se_service)); + strwrite(s, "\r\n"); + } + return (NULL); + } + + /* Try matching a service in inetd.conf with the request */ + for (sep = servtab; sep; sep = sep->se_next) { + if (!ISMUX(sep)) + continue; + if (!strcasecmp(service, sep->se_service)) { + if (ISMUXPLUS(sep)) { + strwrite(s, "+Go\r\n"); + } + return (sep); + } + } + strwrite(s, "-Service not available\r\n"); + return (NULL); +} diff --git a/inetd.tproj/pathnames.h b/inetd.tproj/pathnames.h new file mode 100644 index 0000000..4a7b367 --- /dev/null +++ b/inetd.tproj/pathnames.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +#define _PATH_INETDCONF "/etc/inetd.conf" + +#ifndef _PATH_VARRUN +#define _PATH_VARRUN "/var/run/" +#endif + +#define _PATH_INETDPID _PATH_VARRUN "inetd.pid" diff --git a/ipfw.tproj/Makefile b/ipfw.tproj/Makefile new file mode 100644 index 0000000..7114d40 --- /dev/null +++ b/ipfw.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ipfw + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ipfw.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble ipfw.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /Library/Executables +PDO_UNIX_INSTALLDIR = /bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ipfw.tproj/Makefile.postamble b/ipfw.tproj/Makefile.postamble new file mode 100644 index 0000000..ef51853 --- /dev/null +++ b/ipfw.tproj/Makefile.postamble @@ -0,0 +1,104 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# + +install-man-page: + install -d $(DSTROOT)/usr/share/man/man8 + install -c -m 444 ipfw.8 $(DSTROOT)/usr/share/man/man8/ipfw.8 diff --git a/ipfw.tproj/Makefile.preamble b/ipfw.tproj/Makefile.preamble new file mode 100644 index 0000000..a4606c6 --- /dev/null +++ b/ipfw.tproj/Makefile.preamble @@ -0,0 +1,140 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +DSTROOT = $(HOME) + +AFTER_INSTALL += install-man-page + diff --git a/ipfw.tproj/PB.project b/ipfw.tproj/PB.project new file mode 100644 index 0000000..ab3c121 --- /dev/null +++ b/ipfw.tproj/PB.project @@ -0,0 +1,25 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + OTHER_LINKED = (ipfw.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, ipfw.8); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ipfw; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Library/Executables; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ipfw.tproj/ipfw.8 b/ipfw.tproj/ipfw.8 new file mode 100644 index 0000000..26a7980 --- /dev/null +++ b/ipfw.tproj/ipfw.8 @@ -0,0 +1,733 @@ +.\" +.\" $Id: ipfw.8,v 1.1.1.1 2000/01/11 01:48:49 wsanchez Exp $ +.\" +.Dd July 20, 1996 +.Dt IPFW 8 SMM +.Os FreeBSD +.Sh NAME +.Nm ipfw +.Nd controlling utility for IP firewall +.Sh SYNOPSIS +.Nm ipfw +.Op Fl q +.Oo +.Fl p Ar preproc +.Op Fl D Ar macro Ns Op Ns =value +.Op Fl U Ar macro +.Oc +file +.Nm ipfw +.Oo +.Fl f +| +.Fl q +.Oc +flush +.Nm ipfw +.Oo +.Fl q +.Oc +zero +.Op Ar number ... +.Nm ipfw +delete +.Ar number ... +.Nm ipfw +.Op Fl aftN +list +.Op Ar number ... +.Nm ipfw +.Oo +.Fl ftN +.Oc +show +.Op Ar number ... +.Nm ipfw +.Oo +.Fl q +.Oc +add +.Op Ar number +.Ar action +.Op log +.Ar proto +from +.Ar src +to +.Ar dst +.Op via Ar name | ipno +.Op Ar options +.Sh DESCRIPTION +If used as shown in the first synopsis line, the +.Ar file +will be read line by line and applied as arguments to the +.Nm +command. +.Pp +Optionally, a preprocessor can be specified using +.Fl p Ar preproc +where +.Ar file +is to be piped through. Useful preprocessors include +.Xr cpp 1 +and +.Xr m4 1 . +If +.Ar preproc +doesn't start with a slash as its first character, the usual +.Ev PATH +name search is performed. Care should be taken with this in environments +where not all filesystems are mounted (yet) by the time +.Nm +is being run (e. g. since they are mounted over NFS). Once +.Fl p +has been specified, optional +.Fl D +and +.Fl U +specifications can follow and will be passed on to the preprocessor. +This allows for flexible configuration files (like conditionalizing +them on the local hostname) and the use of macros to centralize +frequently required arguments like IP addresses. +.Pp +Each packet that has been received or is about to be sent goes through +the +.Nm +rules. In the case of a host acting as a gateway, packets that are +forwarded by the host are processed by +.Nm +twice +.Po +once when entering, and once when leaving +.Pc . +Each packet can be filtered based on the following information that is +associated with it: +.Pp +.Bl -tag -offset indent -compact -width xxxx +.It Receive Interface Pq Ar recv +Interface over which the packet was received +.It Transmit Interface Pq Ar xmit +Interface over which the packet would be transmitted +.It Incoming Pq Ar in +Packet was just received +.It Outgoing Pq Ar out +Packet would be transmitted +.It Source IP Address +Sender's IP Address +.It Destination IP Address +Target's IP Address +.It Protocol +IP protocol, including but not limited to IP +.Pq Ar ip , +UDP +.Pq Ar udp , +TCP +.Pq Ar tcp , +or +ICMP +.Pq Ar icmp +.It Source Port +Sender's UDP or TCP port +.It Destination Port +Target's UDP or TCP port +.It Connection Setup Flag Pq Ar setup +This packet is a request to setup a TCP connection +.It Connection Established Flag Pq Ar established +This packet is part of an established TCP connection +.It All TCP Flags Pq Ar tcpflags +One or more of the TCP flags: close connection +.Pq Ar fin , +open connection +.Pq Ar syn , +reset connection +.Pq Ar rst , +push +.Pq Ar psh , +acknowledgment +.Pq Ar ack , +and +urgent +.Pq Ar urg +.It Fragment Flag Pq Ar frag +This packet is a fragment of an IP packet +.It IP Options Pq Ar ipoptions +One or more of the IP options: strict source route +.Pq Ar ssrr , +loose source route +.Pq Ar lsrr , +record route +.Pq Ar rr , +and timestamp +.Pq Ar ts +.It ICMP Types Pq Ar icmptypes +One or more of the ICMP types: echo reply +.Pq Ar 0 , +destination unreachable +.Pq Ar 3 , +source quench +.Pq Ar 4 , +redirect +.Pq Ar 5 , +echo request +.Pq Ar 8 , +router advertisement +.Pq Ar 9 , +router solicitation +.Pq Ar 10 , +time-to-live exceeded +.Pq Ar 11 , +IP header bad +.Pq Ar 12 , +timestamp request +.Pq Ar 13 , +timestamp reply +.Pq Ar 14 , +information request +.Pq Ar 15 , +information reply +.Pq Ar 16 , +address mask request +.Pq Ar 17 , +and address mask reply +.Pq Ar 18 +.El +.Pp +Note that may be dangerous to filter on the source IP address or +source TCP/UDP port because either or both could easily be spoofed. +.Pp +The +.Nm +code works by going through the rule-list for each packet +until a match is found. +All rules have two associated counters, a packet count and +a byte count. +These counters are updated when a packet matches the rule. +.Pp +The rules are ordered by a +.Dq line-number +from 1 to 65534 that is used +to order and delete rules. Rules are tried in increasing order, and the +first rule that matches a packet applies. +Multiple rules may share the same number and apply in +the order in which they were added. +.Pp +If a rule is added without a number, it is numbered 100 higher than the highest +defined rule number, unless the highest defined rule number is 65435 or +greater, in which case new rules are given that same number. +.Pp +The delete operation deletes the first rule with number +.Ar number , +if any. +.Pp +The list command prints out the current rule set. +.Pp +The show command is equivalent to +.Sq ipfw -a list . +.Pp +The zero operation zeroes the counters associated with rule number +.Ar number . +.Pp +The flush operation removes all rules. +.Pp +Any command beginning with a +.Sq # , +or being all blank, is ignored. +.Pp +One rule is always present: +.Bd -literal -offset center +65535 deny all from any to any +.Ed +.Pp +This rule is the default policy, i.e., don't allow anything at all. +Your job in setting up rules is to modify this policy to match your +needs. +.Pp +However, if the kernel option +.Dq IPFIREWALL_DEFAULT_TO_ACCEPT +is active, the rule is instead: +.Bd -literal -offset center +65535 allow all from any to any +.Ed +.Pp +This variation lets everything pass through. This option should only be +activated in particular circumstances, such as if you use the firewall +system as an on-demand denial-of-service filter that is normally wide open. +.Pp +The following options are available: +.Bl -tag -width flag +.It Fl a +While listing, show counter values. See also +.Dq show +command. +.It Fl f +Don't ask for confirmation for commands that can cause problems if misused +(i.e. flush). +.Ar Note , +if there is no tty associated with the process, this is implied. +.It Fl q +While adding, zeroing or flushing, be quiet about actions (implies '-f'). +This is useful for adjusting rules by executing multiple +.Nm +commands in a script +.Po +e.g., +.Sq sh /etc/rc.firewall +.Pc , +or by processing a file of many +.Nm +rules, +across a remote login session. If a flush is performed in normal +(verbose) mode (with the default kernel configuration), it prints a message. +Because all rules are flushed, the +message cannot be delivered to the login session. This causes the +remote login session to be closed and the remainder of the ruleset is +not processed. Access to the console is required to recover. +.It Fl t +While listing, show last match timestamp. +.It Fl N +Try to resolve addresses and service names in output. +.El +.Pp +.Ar action : +.Bl -hang -offset flag -width 1234567890123456 +.It Ar allow +Allow packets that match rule. +The search terminates. Aliases are +.Ar pass , +.Ar permit , +and +.Ar accept . +.It Ar deny +Discard packets that match this rule. +The search terminates. +.Ar Drop +is an alias for +.Ar deny . +.It Ar reject +(Deprecated.) Discard packets that match this rule, and try to send an ICMP +host unreachable notice. +The search terminates. +.It Ar unreach code +Discard packets that match this rule, and try to send an ICMP +unreachable notice with code +.Ar code , +where +.Ar code +is a number from zero to 255, or one of these aliases: +.Ar net , +.Ar host , +.Ar protocol , +.Ar port , +.Ar needfrag , +.Ar srcfail , +.Ar net-unknown , +.Ar host-unknown , +.Ar isolated , +.Ar net-prohib , +.Ar host-prohib , +.Ar tosnet , +.Ar toshost , +.Ar filter-prohib , +.Ar host-precedence , +or +.Ar precedence-cutoff . +The search terminates. +.It Ar reset +TCP packets only. Discard packets that match this rule, +and try to send a TCP reset +.Pq RST +notice. +The search terminates. +.It Ar count +Update counters for all packets that match rule. +The search continues with the next rule. +.It Ar divert port +Divert packets that match this rule to the +.Xr divert 4 +socket bound to port +.Ar port . +The search terminates. +.It Ar tee port +Send a copy of packets matching this rule to the +.Xr divert 4 +socket bound to port +.Ar port . +The search continues with the next rule. This feature is not yet implemeted. +.It Ar fwd ipaddr Op ,port +Change the next-hop on matching packets to +.Ar ipaddr , +which can be an IP address in dotted quad or a host name. +If +.Ar ipaddr +is not a directly-reachable address, the route +as found in the local routing table for that IP is used +instead. +If +.Ar ipaddr +is a local address, then on a packet entering the system from a remote +host it will be diverted to +.Ar port +on the local machine, keeping the local address of the socket set +to the original IP address the packet was destined for. This is intended +for use with transparent proxy servers. If the IP is not +a local address then the port number (if specified) is ignored and +the rule only applies to packets leaving the system. This will +also map addresses to local ports when packets are generated locally. +The search terminates if this rule matches. If the port number is not +given then the port number in the packet is used, so that a packet for +an external machine port Y would be forwarded to local port Y. The kernel +must have been compiled with optiions IPFIREWALL_FORWARD. +.It Ar skipto number +Skip all subsequent rules numbered less than +.Ar number . +The search continues with the first rule numbered +.Ar number +or higher. +.El +.Pp +If a packet matches more than one +.Ar divert +and/or +.Ar tee +rule, all but the last are ignored. +.Pp +If the kernel was compiled with +.Dv IPFIREWALL_VERBOSE , +then when a packet matches a rule with the +.Ar log +keyword a message will be printed on the console. +If the kernel was compiled with the +.Dv IPFIREWALL_VERBOSE_LIMIT +option, then logging will cease after the number of packets +specified by the option are received for that particular +chain entry. Logging may then be re-enabled by clearing +the packet counter for that entry. +.Pp +Console logging and the log limit are adjustable dynamically +through the +.Xr sysctl 8 +interface. +.Pp +.Ar proto : +.Bl -hang -offset flag -width 1234567890123456 +.It Ar ip +All packets match. The alias +.Ar all +has the same effect. +.It Ar tcp +Only TCP packets match. +.It Ar udp +Only UDP packets match. +.It Ar icmp +Only ICMP packets match. +.It Ar +Only packets for the specified protocol matches (see +.Pa /etc/protocols +for a complete list). +.El +.Pp +.Ar src +and +.Ar dst : +.Bl -hang -offset flag +.It Ar
+.Op Ar ports +.El +.Pp +The +.Em
+may be specified as: +.Bl -hang -offset flag -width 1234567890123456 +.It Ar ipno +An ipnumber of the form 1.2.3.4. +Only this exact ip number match the rule. +.It Ar ipno/bits +An ipnumber with a mask width of the form 1.2.3.4/24. +In this case all ip numbers from 1.2.3.0 to 1.2.3.255 will match. +.It Ar ipno:mask +An ipnumber with a mask width of the form 1.2.3.4:255.255.240.0. +In this case all ip numbers from 1.2.0.0 to 1.2.15.255 will match. +.El +.Pp +The sense of the match can be inverted by preceding an address with the +.Dq not +modifier, causing all other addresses to be matched instead. This +does not affect the selection of port numbers. +.Pp +With the TCP and UDP protocols, optional +.Em ports +may be specified as: +.Pp +.Bl -hang -offset flag +.It Ns {port|port-port} Ns Op ,port Ns Op ,... +.El +.Pp +Service names (from +.Pa /etc/services ) +may be used instead of numeric port values. +A range may only be specified as the first value, +and the length of the port list is limited to +.Dv IP_FW_MAX_PORTS +(as defined in +.Pa /usr/src/sys/netinet/ip_fw.h ) +ports. +.Pp +Fragmented packets which have a non-zero offset (i.e. not the first +fragment) will never match a rule which has one or more port +specifications. See the +.Ar frag +option for details on matching fragmented packets. +.Pp +Rules can apply to packets when they are incoming, or outgoing, or both. +The +.Ar in +keyword indicates the rule should only match incoming packets. +The +.Ar out +keyword indicates the rule should only match outgoing packets. +.Pp +To match packets going through a certain interface, specify +the interface using +.Ar via : +.Bl -hang -offset flag -width 1234567890123456 +.It Ar via ifX +Packet must be going through interface +.Ar ifX. +.It Ar via if* +Packet must be going through interface +.Ar ifX , +where X is any unit number. +.It Ar via any +Packet must be going through +.Em some +interface. +.It Ar via ipno +Packet must be going through the interface having IP address +.Ar ipno . +.El +.Pp +The +.Ar via +keyword causes the interface to always be checked. +If +.Ar recv +or +.Ar xmit +is used instead of +.Ar via , +then the only receive or transmit interface (respectively) is checked. +By specifying both, it is possible to match packets based on both receive +and transmit interface, e.g.: +.Pp +.Dl "ipfw add 100 deny ip from any to any out recv ed0 xmit ed1" +.Pp +The +.Ar recv +interface can be tested on either incoming or outgoing packets, while the +.Ar xmit +interface can only be tested on outgoing packets. So +.Ar out +is required (and +.Ar in +invalid) whenver +.Ar xmit +is used. Specifying +.Ar via +together with +.Ar xmit +or +.Ar recv +is invalid. +.Pp +A packet may not have a receive or transmit interface: packets originating +from the local host have no receive interface. while packets destined for +the local host have no transmit interface. +.Pp +Additional +.Ar options : +.Bl -hang -offset flag -width 1234567890123456 +.It frag +Matches if the packet is a fragment and this is not the first fragment +of the datagram. +.Ar frag +may not be used in conjunction with either +.Ar tcpflags +or TCP/UDP port specifications. +.It in +Matches if this packet was on the way in. +.It out +Matches if this packet was on the way out. +.It ipoptions Ar spec +Matches if the IP header contains the comma separated list of +options specified in +.Ar spec . +The supported IP options are: +.Ar ssrr +(strict source route), +.Ar lsrr +(loose source route), +.Ar rr +(record packet route), and +.Ar ts +(timestamp). +The absence of a particular option may be denoted +with a +.Dq ! . +.It established +Matches packets that have the RST or ACK bits set. +TCP packets only. +.It setup +Matches packets that have the SYN bit set but no ACK bit. +TCP packets only. +.It tcpflags Ar spec +Matches if the TCP header contains the comma separated list of +flags specified in +.Ar spec . +The supported TCP flags are: +.Ar fin , +.Ar syn , +.Ar rst , +.Ar psh , +.Ar ack , +and +.Ar urg . +The absence of a particular flag may be denoted +with a +.Dq ! . +A rule which contains a +.Ar tcpflags +specification can never match a fragmented packet which has +a non-zero offset. See the +.Ar frag +option for details on matching fragmented packets. +.It icmptypes Ar types +Matches if the ICMP type is in the list +.Ar types . +The list may be specified as any combination of ranges +or individual types separated by commas. +.El +.Sh CHECKLIST +Here are some important points to consider when designing your +rules: +.Bl -bullet -hang -offset flag +.It +Remember that you filter both packets going in and out. +Most connections need packets going in both directions. +.It +Remember to test very carefully. +It is a good idea to be near the console when doing this. +.It +Don't forget the loopback interface. +.El +.Sh FINE POINTS +There is one kind of packet that the firewall will always discard, +that is an IP fragment with a fragment offset of one. +This is a valid packet, but it only has one use, to try to circumvent +firewalls. +.Pp +If you are logged in over a network, loading the KLD version of +.Nm +is probably not as straightforward as you would think. +I recommend this command line: +.Bd -literal -offset center +kldload /modules/ipfw.ko && \e +ipfw add 32000 allow all from any to any +.Ed +.Pp +Along the same lines, doing an +.Bd -literal -offset center +ipfw flush +.Ed +.Pp +in similar surroundings is also a bad idea. +.Pp +The IP filter list may not be modified if the system security level +is set to 3 or higher +.Po +see +.Xr init 8 +for information on system security levels +.Pc . +.Sh PACKET DIVERSION +A divert socket bound to the specified port will receive all packets diverted +to that port; see +.Xr divert 4 . +If no socket is bound to the destination port, or if the kernel +wasn't compiled with divert socket support, diverted packets are dropped. +.Sh EXAMPLES +This command adds an entry which denies all tcp packets from +.Em cracker.evil.org +to the telnet port of +.Em wolf.tambov.su +from being forwarded by the host: +.Pp +.Dl ipfw add deny tcp from cracker.evil.org to wolf.tambov.su 23 +.Pp +This one disallows any connection from the entire crackers network to +my host: +.Pp +.Dl ipfw add deny all from 123.45.67.0/24 to my.host.org +.Pp +Here is a good usage of the +.Ar list +command to see accounting records +and timestamp information: +.Pp +.Dl ipfw -at l +.Pp +or in short form without timestamps: +.Pp +.Dl ipfw -a l +.Pp +This rule diverts all incoming packets from 192.168.2.0/24 to divert port 5000: +.Pp +.Dl ipfw divert 5000 all from 192.168.2.0/24 to any in +.Sh SEE ALSO +.Xr cpp 1 , +.Xr m4 1 , +.Xr divert 4 , +.Xr ip 4 , +.Xr ipfirewall 4 , +.Xr protocols 5 , +.Xr services 5 , +.Xr init 8 , +.Xr kldload 8 , +.Xr reboot 8 , +.Xr sysctl 8 , +.Xr syslogd 8 . +.Sh BUGS +.Pp +.Em WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!WARNING!!WARNING!! +.Pp +This program can put your computer in rather unusable state. When +using it for the first time, work on the console of the computer, and +do +.Em NOT +do anything you don't understand. +.Pp +When manipulating/adding chain entries, service and protocol names are +not accepted. +.Pp +Incoming packet fragments diverted by +.Ar divert +are reassembled before delivery to the socket, whereas fragments diverted via +.Ar tee +are not. +.Pp +Port aliases containing dashes cannot be first in a list. +.Pp +The +.Dq tee +action is unimplemented. +.Sh AUTHORS +.An Ugen J. S. Antsilevich , +.An Poul-Henning Kamp , +.An Alex Nash , +.An Archie Cobbs . +API based upon code written by +.An Daniel Boulet +for BSDI. +.Sh HISTORY +.Nm +first appeared in +.Fx 2.0 . diff --git a/ipfw.tproj/ipfw.c b/ipfw.tproj/ipfw.c new file mode 100644 index 0000000..7992ec4 --- /dev/null +++ b/ipfw.tproj/ipfw.c @@ -0,0 +1,1613 @@ +/* + * Copyright (c) 1996 Alex Nash, Paul Traina, Poul-Henning Kamp + * Copyright (c) 1994 Ugen J.S.Antsilevich + * + * Idea and grammar partially left from: + * Copyright (c) 1993 Daniel Boulet + * + * Redistribution and use in source forms, with and without modification, + * are permitted provided that this entire comment appears intact. + * + * Redistribution in binary form may occur without any restrictions. + * Obviously, it would be nice if you gave credit where credit is due + * but requiring it would be too onerous. + * + * This software is provided ``AS IS'' without any warranties of any kind. + * + * NEW command line interface for IP firewall facility + * + * $Id: ipfw.c,v 1.2 2000/06/07 04:22:47 lindak Exp $ + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include /* def. of struct route */ +#include +#include +#include +#include +#include + +int lineno = -1; + +int s; /* main RAW socket */ +int do_resolv=0; /* Would try to resolve all */ +int do_acct=0; /* Show packet/byte count */ +int do_time=0; /* Show time stamps */ +int do_quiet=0; /* Be quiet in add and flush */ +int do_force=0; /* Don't ask for confirmation */ +int do_pipe=0; /* this cmd refers to a pipe */ + +struct icmpcode { + int code; + char *str; +}; + +static struct icmpcode icmpcodes[] = { + { ICMP_UNREACH_NET, "net" }, + { ICMP_UNREACH_HOST, "host" }, + { ICMP_UNREACH_PROTOCOL, "protocol" }, + { ICMP_UNREACH_PORT, "port" }, + { ICMP_UNREACH_NEEDFRAG, "needfrag" }, + { ICMP_UNREACH_SRCFAIL, "srcfail" }, + { ICMP_UNREACH_NET_UNKNOWN, "net-unknown" }, + { ICMP_UNREACH_HOST_UNKNOWN, "host-unknown" }, + { ICMP_UNREACH_ISOLATED, "isolated" }, + { ICMP_UNREACH_NET_PROHIB, "net-prohib" }, + { ICMP_UNREACH_HOST_PROHIB, "host-prohib" }, + { ICMP_UNREACH_TOSNET, "tosnet" }, + { ICMP_UNREACH_TOSHOST, "toshost" }, + { ICMP_UNREACH_FILTER_PROHIB, "filter-prohib" }, + { ICMP_UNREACH_HOST_PRECEDENCE, "host-precedence" }, + { ICMP_UNREACH_PRECEDENCE_CUTOFF, "precedence-cutoff" }, + { 0, NULL } +}; + +static void show_usage(const char *fmt, ...); + +static int +mask_bits(struct in_addr m_ad) +{ + int h_fnd=0,h_num=0,i; + u_long mask; + + mask=ntohl(m_ad.s_addr); + for (i=0;i>1; + } + return h_num; +} + +static void +print_port(prot, port, comma) + u_char prot; + u_short port; + const char *comma; +{ + struct servent *se; + struct protoent *pe; + const char *protocol; + int printed = 0; + + if (do_resolv) { + pe = getprotobynumber(prot); + if (pe) + protocol = pe->p_name; + else + protocol = NULL; + + se = getservbyport(htons(port), protocol); + if (se) { + printf("%s%s", comma, se->s_name); + printed = 1; + } + } + if (!printed) + printf("%s%d",comma,port); +} + +static void +print_iface(char *key, union ip_fw_if *un, int byname) +{ + char ifnb[FW_IFNLEN+1]; + + if (byname) { + strncpy(ifnb, un->fu_via_if.name, FW_IFNLEN); + ifnb[FW_IFNLEN]='\0'; + if (un->fu_via_if.unit == -1) + printf(" %s %s*", key, ifnb); + else + printf(" %s %s%d", key, ifnb, un->fu_via_if.unit); + } else if (un->fu_via_ip.s_addr != 0) { + printf(" %s %s", key, inet_ntoa(un->fu_via_ip)); + } else + printf(" %s any", key); +} + +static void +print_reject_code(int code) +{ + struct icmpcode *ic; + + for (ic = icmpcodes; ic->str; ic++) + if (ic->code == code) { + printf("%s", ic->str); + return; + } + printf("%u", code); +} + +static void +show_ipfw(struct ip_fw *chain, int pcwidth, int bcwidth) +{ + char *comma; + u_long adrt; + struct hostent *he; + struct protoent *pe; + int i, mb; + int nsp = IP_FW_GETNSRCP(chain); + int ndp = IP_FW_GETNDSTP(chain); + + if (do_resolv) + setservent(1/*stayopen*/); + + printf("%05u ", chain->fw_number); + + if (do_acct) + printf("%*qu %*qu ",pcwidth,chain->fw_pcnt,bcwidth,chain->fw_bcnt); + + if (do_time) + { + if (chain->timestamp) + { + char timestr[30]; + + strcpy(timestr, ctime((time_t *)&chain->timestamp)); + *strchr(timestr, '\n') = '\0'; + printf("%s ", timestr); + } + else + printf(" "); + } + + switch (chain->fw_flg & IP_FW_F_COMMAND) + { + case IP_FW_F_ACCEPT: + printf("allow"); + break; + case IP_FW_F_DENY: + printf("deny"); + break; + case IP_FW_F_COUNT: + printf("count"); + break; + case IP_FW_F_DIVERT: + printf("divert %u", chain->fw_divert_port); + break; + case IP_FW_F_TEE: + printf("tee %u", chain->fw_divert_port); + break; + case IP_FW_F_SKIPTO: + printf("skipto %u", chain->fw_skipto_rule); + break; + case IP_FW_F_PIPE: + printf("pipe %u", chain->fw_skipto_rule); + break ; + case IP_FW_F_REJECT: + if (chain->fw_reject_code == IP_FW_REJECT_RST) + printf("reset"); + else { + printf("unreach "); + print_reject_code(chain->fw_reject_code); + } + break; + case IP_FW_F_FWD: + printf("fwd %s", inet_ntoa(chain->fw_fwd_ip.sin_addr)); + if(chain->fw_fwd_ip.sin_port) + printf(",%d", chain->fw_fwd_ip.sin_port); + break; + default: + errx(EX_OSERR, "impossible"); + } + + if (chain->fw_flg & IP_FW_F_PRN) + printf(" log"); + + pe = getprotobynumber(chain->fw_prot); + if (pe) + printf(" %s", pe->p_name); + else + printf(" %u", chain->fw_prot); + + printf(" from %s", chain->fw_flg & IP_FW_F_INVSRC ? "not " : ""); + + adrt=ntohl(chain->fw_smsk.s_addr); + if (adrt==ULONG_MAX && do_resolv) { + adrt=(chain->fw_src.s_addr); + he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET); + if (he==NULL) { + printf(inet_ntoa(chain->fw_src)); + } else + printf("%s",he->h_name); + } else { + if (adrt!=ULONG_MAX) { + mb=mask_bits(chain->fw_smsk); + if (mb == 0) { + printf("any"); + } else { + if (mb > 0) { + printf(inet_ntoa(chain->fw_src)); + printf("/%d",mb); + } else { + printf(inet_ntoa(chain->fw_src)); + printf(":"); + printf(inet_ntoa(chain->fw_smsk)); + } + } + } else + printf(inet_ntoa(chain->fw_src)); + } + + if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) { + comma = " "; + for (i = 0; i < nsp; i++) { + print_port(chain->fw_prot, chain->fw_uar.fw_pts[i], comma); + if (i==0 && (chain->fw_flg & IP_FW_F_SRNG)) + comma = "-"; + else + comma = ","; + } + } + + printf(" to %s", chain->fw_flg & IP_FW_F_INVDST ? "not " : ""); + + adrt=ntohl(chain->fw_dmsk.s_addr); + if (adrt==ULONG_MAX && do_resolv) { + adrt=(chain->fw_dst.s_addr); + he=gethostbyaddr((char *)&adrt,sizeof(u_long),AF_INET); + if (he==NULL) { + printf(inet_ntoa(chain->fw_dst)); + } else + printf("%s",he->h_name); + } else { + if (adrt!=ULONG_MAX) { + mb=mask_bits(chain->fw_dmsk); + if (mb == 0) { + printf("any"); + } else { + if (mb > 0) { + printf(inet_ntoa(chain->fw_dst)); + printf("/%d",mb); + } else { + printf(inet_ntoa(chain->fw_dst)); + printf(":"); + printf(inet_ntoa(chain->fw_dmsk)); + } + } + } else + printf(inet_ntoa(chain->fw_dst)); + } + + if (chain->fw_prot == IPPROTO_TCP || chain->fw_prot == IPPROTO_UDP) { + comma = " "; + for (i = 0; i < ndp; i++) { + print_port(chain->fw_prot, chain->fw_uar.fw_pts[nsp+i], comma); + if (i==0 && (chain->fw_flg & IP_FW_F_DRNG)) + comma = "-"; + else + comma = ","; + } + } + + /* Direction */ + if ((chain->fw_flg & IP_FW_F_IN) && !(chain->fw_flg & IP_FW_F_OUT)) + printf(" in"); + if (!(chain->fw_flg & IP_FW_F_IN) && (chain->fw_flg & IP_FW_F_OUT)) + printf(" out"); + + /* Handle hack for "via" backwards compatibility */ + if ((chain->fw_flg & IF_FW_F_VIAHACK) == IF_FW_F_VIAHACK) { + print_iface("via", + &chain->fw_in_if, chain->fw_flg & IP_FW_F_IIFNAME); + } else { + /* Receive interface specified */ + if (chain->fw_flg & IP_FW_F_IIFACE) + print_iface("recv", &chain->fw_in_if, + chain->fw_flg & IP_FW_F_IIFNAME); + /* Transmit interface specified */ + if (chain->fw_flg & IP_FW_F_OIFACE) + print_iface("xmit", &chain->fw_out_if, + chain->fw_flg & IP_FW_F_OIFNAME); + } + + if (chain->fw_flg & IP_FW_F_FRAG) + printf(" frag"); + + if (chain->fw_ipopt || chain->fw_ipnopt) { + int _opt_printed = 0; +#define PRINTOPT(x) {if (_opt_printed) printf(",");\ + printf(x); _opt_printed = 1;} + + printf(" ipopt "); + if (chain->fw_ipopt & IP_FW_IPOPT_SSRR) PRINTOPT("ssrr"); + if (chain->fw_ipnopt & IP_FW_IPOPT_SSRR) PRINTOPT("!ssrr"); + if (chain->fw_ipopt & IP_FW_IPOPT_LSRR) PRINTOPT("lsrr"); + if (chain->fw_ipnopt & IP_FW_IPOPT_LSRR) PRINTOPT("!lsrr"); + if (chain->fw_ipopt & IP_FW_IPOPT_RR) PRINTOPT("rr"); + if (chain->fw_ipnopt & IP_FW_IPOPT_RR) PRINTOPT("!rr"); + if (chain->fw_ipopt & IP_FW_IPOPT_TS) PRINTOPT("ts"); + if (chain->fw_ipnopt & IP_FW_IPOPT_TS) PRINTOPT("!ts"); + } + + if (chain->fw_tcpf & IP_FW_TCPF_ESTAB) + printf(" established"); + else if (chain->fw_tcpf == IP_FW_TCPF_SYN && + chain->fw_tcpnf == IP_FW_TCPF_ACK) + printf(" setup"); + else if (chain->fw_tcpf || chain->fw_tcpnf) { + int _flg_printed = 0; +#define PRINTFLG(x) {if (_flg_printed) printf(",");\ + printf(x); _flg_printed = 1;} + + printf(" tcpflg "); + if (chain->fw_tcpf & IP_FW_TCPF_FIN) PRINTFLG("fin"); + if (chain->fw_tcpnf & IP_FW_TCPF_FIN) PRINTFLG("!fin"); + if (chain->fw_tcpf & IP_FW_TCPF_SYN) PRINTFLG("syn"); + if (chain->fw_tcpnf & IP_FW_TCPF_SYN) PRINTFLG("!syn"); + if (chain->fw_tcpf & IP_FW_TCPF_RST) PRINTFLG("rst"); + if (chain->fw_tcpnf & IP_FW_TCPF_RST) PRINTFLG("!rst"); + if (chain->fw_tcpf & IP_FW_TCPF_PSH) PRINTFLG("psh"); + if (chain->fw_tcpnf & IP_FW_TCPF_PSH) PRINTFLG("!psh"); + if (chain->fw_tcpf & IP_FW_TCPF_ACK) PRINTFLG("ack"); + if (chain->fw_tcpnf & IP_FW_TCPF_ACK) PRINTFLG("!ack"); + if (chain->fw_tcpf & IP_FW_TCPF_URG) PRINTFLG("urg"); + if (chain->fw_tcpnf & IP_FW_TCPF_URG) PRINTFLG("!urg"); + } + if (chain->fw_flg & IP_FW_F_ICMPBIT) { + int type_index; + int first = 1; + + printf(" icmptype"); + + for (type_index = 0; type_index < IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8; ++type_index) + if (chain->fw_uar.fw_icmptypes[type_index / (sizeof(unsigned) * 8)] & + (1U << (type_index % (sizeof(unsigned) * 8)))) { + printf("%c%d", first == 1 ? ' ' : ',', type_index); + first = 0; + } + } + printf("\n"); + if (do_resolv) + endservent(); +} + +static void +list(ac, av) + int ac; + char **av; +{ + struct ip_fw *rules; + struct dn_pipe *pipes; + void *data = NULL; + int pcwidth = 0; + int bcwidth = 0; + int n, num = 0; + + /* get rules or pipes from kernel, resizing array as necessary */ + { + const int unit = do_pipe ? sizeof(*pipes) : sizeof(*rules); + const int ocmd = do_pipe ? IP_DUMMYNET_GET : IP_FW_GET; + int nalloc = 0; + int nbytes; + + while (num >= nalloc) { + nalloc = nalloc * 2 + 200; + nbytes = nalloc * unit; + if ((data = realloc(data, nbytes)) == NULL) + err(EX_OSERR, "realloc"); + if (getsockopt(s, IPPROTO_IP, ocmd, data, &nbytes) < 0) + err(EX_OSERR, "getsockopt(IP_%s_GET)", + do_pipe ? "DUMMYNET" : "FW"); + num = nbytes / unit; + } + } + + /* display requested pipes */ + if (do_pipe) { + u_long rulenum; + + pipes = (struct dn_pipe *) data; + if (ac > 0) + rulenum = strtoul(*av++, NULL, 10); + else + rulenum = 0 ; + for (n = 0; n < num; n++) { + struct dn_pipe *const p = &pipes[n]; + double b = p->bandwidth ; + char buf[30] ; + char qs[30] ; + char plr[30] ; + int l ; + + if (rulenum != 0 && rulenum != p->pipe_nr) + continue; + if (b == 0) + sprintf(buf, "unlimited"); + else if (b >= 1000000) + sprintf(buf, "%7.3f Mbit/s", b/1000000 ); + else if (b >= 1000) + sprintf(buf, "%7.3f Kbit/s", b/1000 ); + else + sprintf(buf, "%7.3f bit/s ", b ); + + if ( (l = p->queue_size_bytes) != 0 ) { + if (l >= 8192) + sprintf(qs,"%d KB", l / 1024); + else + sprintf(qs,"%d B", l); + } else + sprintf(qs,"%3d sl.", p->queue_size); + if (p->plr) + sprintf(plr,"plr %f", 1.0*p->plr/(double)(0x7fffffff)); + else + plr[0]='\0'; + + printf("%05d: %s %4d ms %s %s -- %d pkts (%d B) %d drops\n", + p->pipe_nr, buf, p->delay, qs, plr, + p->r_len, p->r_len_bytes, p->r_drops); + } + free(data); + return; + } + + /* if showing stats, figure out column widths ahead of time */ + rules = (struct ip_fw *) data; + if (do_acct) { + for (n = 0; n < num; n++) { + struct ip_fw *const r = &rules[n]; + char temp[32]; + int width; + + /* packet counter */ + width = sprintf(temp, "%qu", r->fw_pcnt); + if (width > pcwidth) + pcwidth = width; + + /* byte counter */ + width = sprintf(temp, "%qu", r->fw_bcnt); + if (width > bcwidth) + bcwidth = width; + } + } + if (ac == 0) { + /* display all rules */ + for (n = 0; n < num; n++) { + struct ip_fw *const r = &rules[n]; + + show_ipfw(r, pcwidth, bcwidth); + } + } else { + /* display specific rules requested on command line */ + int exitval = EX_OK; + + while (ac--) { + u_long rnum; + char *endptr; + int seen; + + /* convert command line rule # */ + rnum = strtoul(*av++, &endptr, 10); + if (*endptr) { + exitval = EX_USAGE; + warnx("invalid rule number: %s", *(av - 1)); + continue; + } + for (seen = n = 0; n < num; n++) { + struct ip_fw *const r = &rules[n]; + + if (r->fw_number > rnum) + break; + if (r->fw_number == rnum) { + show_ipfw(r, pcwidth, bcwidth); + seen = 1; + } + } + if (!seen) { + /* give precedence to other error(s) */ + if (exitval == EX_OK) + exitval = EX_UNAVAILABLE; + warnx("rule %lu does not exist", rnum); + } + } + if (exitval != EX_OK) + exit(exitval); + } + free(data); +} + +static void +show_usage(const char *fmt, ...) +{ + if (fmt) { + char buf[100]; + va_list args; + + va_start(args, fmt); + vsnprintf(buf, sizeof(buf), fmt, args); + va_end(args); + warnx("error: %s", buf); + } + fprintf(stderr, "usage: ipfw [options]\n" +" flush\n" +" add [number] rule\n" +" delete number ...\n" +" list [number ...]\n" +" show [number ...]\n" +" zero [number ...]\n" +" rule: action proto src dst extras...\n" +" action:\n" +" {allow|permit|accept|pass|deny|drop|reject|unreach code|\n" +" reset|count|skipto num|divert port|tee port|fwd ip} [log]\n" +" proto: {ip|tcp|udp|icmp|}\n" +" src: from [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" +" dst: to [not] {any|ip[{/bits|:mask}]} [{port|port-port},[port],...]\n" +" extras:\n" +" fragment (may not be used with ports or tcpflags)\n" +" in\n" +" out\n" +" {xmit|recv|via} {iface|ip|any}\n" +" {established|setup}\n" +" tcpflags [!]{syn|fin|rst|ack|psh|urg},...\n" +" ipoptions [!]{ssrr|lsrr|rr|ts},...\n" +" icmptypes {type[,type]}...\n"); + + exit(EX_USAGE); +} + +static int +lookup_host (host, ipaddr) + char *host; + struct in_addr *ipaddr; +{ + struct hostent *he = gethostbyname(host); + + if (!he) { + if (inet_aton(host, ipaddr)) + return(0); + else + return(-1); + } + *ipaddr = *(struct in_addr *)he->h_addr_list[0]; + + return(0); +} + +static void +fill_ip(ipno, mask, acp, avp) + struct in_addr *ipno, *mask; + int *acp; + char ***avp; +{ + int ac = *acp; + char **av = *avp; + char *p = 0, md = 0; + + if (ac && !strncmp(*av,"any",strlen(*av))) { + ipno->s_addr = mask->s_addr = 0; av++; ac--; + } else { + p = strchr(*av, '/'); + if (!p) + p = strchr(*av, ':'); + if (p) { + md = *p; + *p++ = '\0'; + } + + if (lookup_host(*av, ipno) != 0) + show_usage("hostname ``%s'' unknown", *av); + switch (md) { + case ':': + if (!inet_aton(p,mask)) + show_usage("bad netmask ``%s''", p); + break; + case '/': + if (atoi(p) == 0) { + mask->s_addr = 0; + } else if (atoi(p) > 32) { + show_usage("bad width ``%s''", p); + } else { + mask->s_addr = + htonl(~0 << (32 - atoi(p))); + } + break; + default: + mask->s_addr = htonl(~0); + break; + } + ipno->s_addr &= mask->s_addr; + av++; + ac--; + } + *acp = ac; + *avp = av; +} + +static void +fill_reject_code(u_short *codep, char *str) +{ + struct icmpcode *ic; + u_long val; + char *s; + + val = strtoul(str, &s, 0); + if (s != str && *s == '\0' && val < 0x100) { + *codep = val; + return; + } + for (ic = icmpcodes; ic->str; ic++) + if (!strcasecmp(str, ic->str)) { + *codep = ic->code; + return; + } + show_usage("unknown ICMP unreachable code ``%s''", str); +} + +static void +add_port(cnt, ptr, off, port) + u_short *cnt, *ptr, off, port; +{ + if (off + *cnt >= IP_FW_MAX_PORTS) + errx(EX_USAGE, "too many ports (max is %d)", IP_FW_MAX_PORTS); + ptr[off+*cnt] = port; + (*cnt)++; +} + +static int +lookup_port(const char *arg, int test, int nodash) +{ + int val; + char *earg, buf[32]; + struct servent *s; + + snprintf(buf, sizeof(buf), "%s", arg); + buf[strcspn(arg, nodash ? "-," : ",")] = 0; + val = (int) strtoul(buf, &earg, 0); + if (!*buf || *earg) { + setservent(1); + if ((s = getservbyname(buf, NULL))) { + val = htons(s->s_port); + } else { + if (!test) { + errx(EX_DATAERR, "unknown port ``%s''", arg); + } + val = -1; + } + } else { + if (val < 0 || val > 0xffff) { + if (!test) { + errx(EX_DATAERR, "port ``%s'' out of range", arg); + } + val = -1; + } + } + return(val); +} + +static int +fill_port(cnt, ptr, off, arg) + u_short *cnt, *ptr, off; + char *arg; +{ + char *s; + int initial_range = 0; + + s = arg + strcspn(arg, "-,"); /* first port name can't have a dash */ + if (*s == '-') { + *s++ = '\0'; + if (strchr(arg, ',')) + errx(EX_USAGE, "port range must be first in list"); + add_port(cnt, ptr, off, *arg ? lookup_port(arg, 0, 0) : 0x0000); + arg = s; + s = strchr(arg,','); + if (s) + *s++ = '\0'; + add_port(cnt, ptr, off, *arg ? lookup_port(arg, 0, 0) : 0xffff); + arg = s; + initial_range = 1; + } + while (arg != NULL) { + s = strchr(arg,','); + if (s) + *s++ = '\0'; + add_port(cnt, ptr, off, lookup_port(arg, 0, 0)); + arg = s; + } + return initial_range; +} + +static void +fill_tcpflag(set, reset, vp) + u_char *set, *reset; + char **vp; +{ + char *p = *vp,*q; + u_char *d; + + while (p && *p) { + struct tpcflags { + char * name; + u_char value; + } flags[] = { + { "syn", IP_FW_TCPF_SYN }, + { "fin", IP_FW_TCPF_FIN }, + { "ack", IP_FW_TCPF_ACK }, + { "psh", IP_FW_TCPF_PSH }, + { "rst", IP_FW_TCPF_RST }, + { "urg", IP_FW_TCPF_URG } + }; + int i; + + if (*p == '!') { + p++; + d = reset; + } else { + d = set; + } + q = strchr(p, ','); + if (q) + *q++ = '\0'; + for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) + if (!strncmp(p, flags[i].name, strlen(p))) { + *d |= flags[i].value; + break; + } + if (i == sizeof(flags) / sizeof(flags[0])) + show_usage("invalid tcp flag ``%s''", p); + p = q; + } +} + +static void +fill_ipopt(u_char *set, u_char *reset, char **vp) +{ + char *p = *vp,*q; + u_char *d; + + while (p && *p) { + if (*p == '!') { + p++; + d = reset; + } else { + d = set; + } + q = strchr(p, ','); + if (q) + *q++ = '\0'; + if (!strncmp(p,"ssrr",strlen(p))) *d |= IP_FW_IPOPT_SSRR; + if (!strncmp(p,"lsrr",strlen(p))) *d |= IP_FW_IPOPT_LSRR; + if (!strncmp(p,"rr",strlen(p))) *d |= IP_FW_IPOPT_RR; + if (!strncmp(p,"ts",strlen(p))) *d |= IP_FW_IPOPT_TS; + p = q; + } +} + +static void +fill_icmptypes(types, vp, fw_flg) + u_long *types; + char **vp; + u_int *fw_flg; +{ + char *c = *vp; + + while (*c) + { + unsigned long icmptype; + + if ( *c == ',' ) + ++c; + + icmptype = strtoul(c, &c, 0); + + if ( *c != ',' && *c != '\0' ) + show_usage("invalid ICMP type"); + + if (icmptype >= IP_FW_ICMPTYPES_DIM * sizeof(unsigned) * 8) + show_usage("ICMP type out of range"); + + types[icmptype / (sizeof(unsigned) * 8)] |= + 1 << (icmptype % (sizeof(unsigned) * 8)); + *fw_flg |= IP_FW_F_ICMPBIT; + } +} + +static void +delete(ac,av) + int ac; + char **av; +{ + struct ip_fw rule; + struct dn_pipe pipe; + int i; + int exitval = EX_OK; + + memset(&rule, 0, sizeof rule); + memset(&pipe, 0, sizeof pipe); + + av++; ac--; + + /* Rule number */ + while (ac && isdigit(**av)) { + if (do_pipe) { + pipe.pipe_nr = atoi(*av); av++; ac--; + i = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_DEL, + &pipe, sizeof pipe); + if (i) { + exitval = 1; + warn("rule %u: setsockopt(%s)", pipe.pipe_nr, "IP_DUMMYNET_DEL"); + } + } else { + rule.fw_number = atoi(*av); av++; ac--; + i = setsockopt(s, IPPROTO_IP, IP_FW_DEL, &rule, sizeof rule); + if (i) { + exitval = EX_UNAVAILABLE; + warn("rule %u: setsockopt(%s)", rule.fw_number, "IP_FW_DEL"); + } + } + } + if (exitval != EX_OK) + exit(exitval); +} + +static void +verify_interface(union ip_fw_if *ifu) +{ + struct ifreq ifr; + + /* + * If a unit was specified, check for that exact interface. + * If a wildcard was specified, check for unit 0. + */ + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", + ifu->fu_via_if.name, + ifu->fu_via_if.unit == -1 ? 0 : ifu->fu_via_if.unit); + + if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) + warnx("warning: interface ``%s'' does not exist", ifr.ifr_name); +} + +static void +fill_iface(char *which, union ip_fw_if *ifu, int *byname, int ac, char *arg) +{ + if (!ac) + show_usage("missing argument for ``%s''", which); + + /* Parse the interface or address */ + if (!strcmp(arg, "any")) { + ifu->fu_via_ip.s_addr = 0; + *byname = 0; + } else if (!isdigit(*arg)) { + char *q; + + *byname = 1; + strncpy(ifu->fu_via_if.name, arg, sizeof(ifu->fu_via_if.name)); + ifu->fu_via_if.name[sizeof(ifu->fu_via_if.name) - 1] = '\0'; + for (q = ifu->fu_via_if.name; + *q && !isdigit(*q) && *q != '*'; q++) + continue; + ifu->fu_via_if.unit = (*q == '*') ? -1 : atoi(q); + *q = '\0'; + verify_interface(ifu); + } else if (!inet_aton(arg, &ifu->fu_via_ip)) { + show_usage("bad ip address ``%s''", arg); + } else + *byname = 0; +} + +static void +config_pipe(int ac, char **av) +{ + struct dn_pipe pipe; + int i ; + char *end ; + + memset(&pipe, 0, sizeof pipe); + + av++; ac--; + /* Pipe number */ + if (ac && isdigit(**av)) { + pipe.pipe_nr = atoi(*av); av++; ac--; + } + while (ac > 1) { + if (!strncmp(*av,"bw",strlen(*av)) || + ! strncmp(*av,"bandwidth",strlen(*av))) { + pipe.bandwidth = strtoul(av[1], &end, 0); + if (*end == 'K') + end++, pipe.bandwidth *= 1000 ; + else if (*end == 'M') + end++, pipe.bandwidth *= 1000000 ; + if (*end == 'B') + pipe.bandwidth *= 8 ; + av+=2; ac-=2; + } else if (!strncmp(*av,"delay",strlen(*av)) ) { + pipe.delay = strtoul(av[1], NULL, 0); + av+=2; ac-=2; + } else if (!strncmp(*av,"plr",strlen(*av)) ) { + + double d = strtod(av[1], NULL); + pipe.plr = (int)(d*0x7fffffff) ; + av+=2; ac-=2; + } else if (!strncmp(*av,"queue",strlen(*av)) ) { + end = NULL ; + pipe.queue_size = strtoul(av[1], &end, 0); + if (*end == 'K') { + pipe.queue_size_bytes = pipe.queue_size*1024 ; + pipe.queue_size = 0 ; + } else if (*end == 'B') { + pipe.queue_size_bytes = pipe.queue_size ; + pipe.queue_size = 0 ; + } + av+=2; ac-=2; + } else + show_usage("unrecognised option ``%s''", *av); + } + if (pipe.pipe_nr == 0 ) + show_usage("pipe_nr %d be > 0", pipe.pipe_nr); + if (pipe.queue_size > 100 ) + show_usage("queue size %d must be 2 <= x <= 100", pipe.queue_size); + if (pipe.delay > 10000 ) + show_usage("delay %d must be < 10000", pipe.delay); +#if 0 + printf("configuring pipe %d bw %d delay %d size %d\n", + pipe.pipe_nr, pipe.bandwidth, pipe.delay, pipe.queue_size); +#endif + i = setsockopt(s,IPPROTO_IP, IP_DUMMYNET_CONFIGURE, &pipe,sizeof pipe); + if (i) + err(1, "setsockopt(%s)", "IP_DUMMYNET_CONFIGURE"); + +} + +static void +add(ac,av) + int ac; + char **av; +{ + struct ip_fw rule; + int i; + u_char proto; + struct protoent *pe; + int saw_xmrc = 0, saw_via = 0; + + memset(&rule, 0, sizeof rule); + + av++; ac--; + + /* Rule number */ + if (ac && isdigit(**av)) { + rule.fw_number = atoi(*av); av++; ac--; + } + + /* Action */ + if (ac == 0) + show_usage("missing action"); + if (!strncmp(*av,"accept",strlen(*av)) + || !strncmp(*av,"pass",strlen(*av)) + || !strncmp(*av,"allow",strlen(*av)) + || !strncmp(*av,"permit",strlen(*av))) { + rule.fw_flg |= IP_FW_F_ACCEPT; av++; ac--; + } else if (!strncmp(*av,"count",strlen(*av))) { + rule.fw_flg |= IP_FW_F_COUNT; av++; ac--; + } else if (!strncmp(*av,"pipe",strlen(*av))) { + rule.fw_flg |= IP_FW_F_PIPE; av++; ac--; + if (!ac) + show_usage("missing pipe number"); + rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--; + } else if (!strncmp(*av,"divert",strlen(*av))) { + rule.fw_flg |= IP_FW_F_DIVERT; av++; ac--; + if (!ac) + show_usage("missing %s port", "divert"); + rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--; + if (rule.fw_divert_port == 0) { + struct servent *s; + setservent(1); + s = getservbyname(av[-1], "divert"); + if (s != NULL) + rule.fw_divert_port = ntohs(s->s_port); + else + show_usage("illegal %s port", "divert"); + } + } else if (!strncmp(*av,"tee",strlen(*av))) { + rule.fw_flg |= IP_FW_F_TEE; av++; ac--; + if (!ac) + show_usage("missing %s port", "tee divert"); + rule.fw_divert_port = strtoul(*av, NULL, 0); av++; ac--; + if (rule.fw_divert_port == 0) { + struct servent *s; + setservent(1); + s = getservbyname(av[-1], "divert"); + if (s != NULL) + rule.fw_divert_port = ntohs(s->s_port); + else + show_usage("illegal %s port", "tee divert"); + } +#ifndef IPFW_TEE_IS_FINALLY_IMPLEMENTED + err(EX_USAGE, "the ``tee'' action is not implemented"); +#endif + } else if (!strncmp(*av,"fwd",strlen(*av)) || + !strncmp(*av,"forward",strlen(*av))) { + struct in_addr dummyip; + char *pp; + rule.fw_flg |= IP_FW_F_FWD; av++; ac--; + if (!ac) + show_usage("missing forwarding IP address"); + rule.fw_fwd_ip.sin_len = sizeof(struct sockaddr_in); + rule.fw_fwd_ip.sin_family = AF_INET; + rule.fw_fwd_ip.sin_port = 0; + pp = strchr(*av, ':'); + if(pp == NULL) + pp = strchr(*av, ','); + if(pp != NULL) + { + *(pp++) = '\0'; + rule.fw_fwd_ip.sin_port = lookup_port(pp, 1, 1); + if(rule.fw_fwd_ip.sin_port == (unsigned int)-1) + show_usage("illegal forwarding port"); + } + fill_ip(&(rule.fw_fwd_ip.sin_addr), &dummyip, &ac, &av); + if (rule.fw_fwd_ip.sin_addr.s_addr == 0) + show_usage("illegal forwarding IP address"); + + } else if (!strncmp(*av,"skipto",strlen(*av))) { + rule.fw_flg |= IP_FW_F_SKIPTO; av++; ac--; + if (!ac) + show_usage("missing skipto rule number"); + rule.fw_skipto_rule = strtoul(*av, NULL, 0); av++; ac--; + } else if ((!strncmp(*av,"deny",strlen(*av)) + || !strncmp(*av,"drop",strlen(*av)))) { + rule.fw_flg |= IP_FW_F_DENY; av++; ac--; + } else if (!strncmp(*av,"reject",strlen(*av))) { + rule.fw_flg |= IP_FW_F_REJECT; av++; ac--; + rule.fw_reject_code = ICMP_UNREACH_HOST; + } else if (!strncmp(*av,"reset",strlen(*av))) { + rule.fw_flg |= IP_FW_F_REJECT; av++; ac--; + rule.fw_reject_code = IP_FW_REJECT_RST; /* check TCP later */ + } else if (!strncmp(*av,"unreach",strlen(*av))) { + rule.fw_flg |= IP_FW_F_REJECT; av++; ac--; + fill_reject_code(&rule.fw_reject_code, *av); av++; ac--; + } else { + show_usage("invalid action ``%s''", *av); + } + + /* [log] */ + if (ac && !strncmp(*av,"log",strlen(*av))) { + rule.fw_flg |= IP_FW_F_PRN; av++; ac--; + } + + /* protocol */ + if (ac == 0) + show_usage("missing protocol"); + if ((proto = atoi(*av)) > 0) { + rule.fw_prot = proto; av++; ac--; + } else if (!strncmp(*av,"all",strlen(*av))) { + rule.fw_prot = IPPROTO_IP; av++; ac--; + } else if ((pe = getprotobyname(*av)) != NULL) { + rule.fw_prot = pe->p_proto; av++; ac--; + } else { + show_usage("invalid protocol ``%s''", *av); + } + + if (rule.fw_prot != IPPROTO_TCP + && (rule.fw_flg & IP_FW_F_COMMAND) == IP_FW_F_REJECT + && rule.fw_reject_code == IP_FW_REJECT_RST) + show_usage("``reset'' is only valid for tcp packets"); + + /* from */ + if (ac && !strncmp(*av,"from",strlen(*av))) { av++; ac--; } + else + show_usage("missing ``from''"); + + if (ac && !strncmp(*av,"not",strlen(*av))) { + rule.fw_flg |= IP_FW_F_INVSRC; + av++; ac--; + } + if (!ac) + show_usage("missing arguments"); + + fill_ip(&rule.fw_src, &rule.fw_smsk, &ac, &av); + + if (ac && (isdigit(**av) || lookup_port(*av, 1, 1) >= 0)) { + u_short nports = 0; + + if (fill_port(&nports, rule.fw_uar.fw_pts, 0, *av)) + rule.fw_flg |= IP_FW_F_SRNG; + IP_FW_SETNSRCP(&rule, nports); + av++; ac--; + } + + /* to */ + if (ac && !strncmp(*av,"to",strlen(*av))) { av++; ac--; } + else + show_usage("missing ``to''"); + + if (ac && !strncmp(*av,"not",strlen(*av))) { + rule.fw_flg |= IP_FW_F_INVDST; + av++; ac--; + } + if (!ac) + show_usage("missing arguments"); + + fill_ip(&rule.fw_dst, &rule.fw_dmsk, &ac, &av); + + if (ac && (isdigit(**av) || lookup_port(*av, 1, 1) >= 0)) { + u_short nports = 0; + + if (fill_port(&nports, + rule.fw_uar.fw_pts, IP_FW_GETNSRCP(&rule), *av)) + rule.fw_flg |= IP_FW_F_DRNG; + IP_FW_SETNDSTP(&rule, nports); + av++; ac--; + } + + if ((rule.fw_prot != IPPROTO_TCP) && (rule.fw_prot != IPPROTO_UDP) + && (IP_FW_GETNSRCP(&rule) || IP_FW_GETNDSTP(&rule))) { + show_usage("only TCP and UDP protocols are valid" + " with port specifications"); + } + + while (ac) { + if (!strncmp(*av,"in",strlen(*av))) { + rule.fw_flg |= IP_FW_F_IN; + av++; ac--; continue; + } + if (!strncmp(*av,"out",strlen(*av))) { + rule.fw_flg |= IP_FW_F_OUT; + av++; ac--; continue; + } + if (ac && !strncmp(*av,"xmit",strlen(*av))) { + union ip_fw_if ifu; + int byname; + + if (saw_via) { +badviacombo: + show_usage("``via'' is incompatible" + " with ``xmit'' and ``recv''"); + } + saw_xmrc = 1; + av++; ac--; + fill_iface("xmit", &ifu, &byname, ac, *av); + rule.fw_out_if = ifu; + rule.fw_flg |= IP_FW_F_OIFACE; + if (byname) + rule.fw_flg |= IP_FW_F_OIFNAME; + av++; ac--; continue; + } + if (ac && !strncmp(*av,"recv",strlen(*av))) { + union ip_fw_if ifu; + int byname; + + if (saw_via) + goto badviacombo; + saw_xmrc = 1; + av++; ac--; + fill_iface("recv", &ifu, &byname, ac, *av); + rule.fw_in_if = ifu; + rule.fw_flg |= IP_FW_F_IIFACE; + if (byname) + rule.fw_flg |= IP_FW_F_IIFNAME; + av++; ac--; continue; + } + if (ac && !strncmp(*av,"via",strlen(*av))) { + union ip_fw_if ifu; + int byname = 0; + + if (saw_xmrc) + goto badviacombo; + saw_via = 1; + av++; ac--; + fill_iface("via", &ifu, &byname, ac, *av); + rule.fw_out_if = rule.fw_in_if = ifu; + if (byname) + rule.fw_flg |= + (IP_FW_F_IIFNAME | IP_FW_F_OIFNAME); + av++; ac--; continue; + } + if (!strncmp(*av,"fragment",strlen(*av))) { + rule.fw_flg |= IP_FW_F_FRAG; + av++; ac--; continue; + } + if (!strncmp(*av,"ipoptions",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``ipoptions''"); + fill_ipopt(&rule.fw_ipopt, &rule.fw_ipnopt, av); + av++; ac--; continue; + } + if (rule.fw_prot == IPPROTO_TCP) { + if (!strncmp(*av,"established",strlen(*av))) { + rule.fw_tcpf |= IP_FW_TCPF_ESTAB; + av++; ac--; continue; + } + if (!strncmp(*av,"setup",strlen(*av))) { + rule.fw_tcpf |= IP_FW_TCPF_SYN; + rule.fw_tcpnf |= IP_FW_TCPF_ACK; + av++; ac--; continue; + } + if (!strncmp(*av,"tcpflags",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``tcpflags''"); + fill_tcpflag(&rule.fw_tcpf, &rule.fw_tcpnf, av); + av++; ac--; continue; + } + } + if (rule.fw_prot == IPPROTO_ICMP) { + if (!strncmp(*av,"icmptypes",strlen(*av))) { + av++; ac--; + if (!ac) + show_usage("missing argument" + " for ``icmptypes''"); + fill_icmptypes(rule.fw_uar.fw_icmptypes, + av, &rule.fw_flg); + av++; ac--; continue; + } + } + show_usage("unknown argument ``%s''", *av); + } + + /* No direction specified -> do both directions */ + if (!(rule.fw_flg & (IP_FW_F_OUT|IP_FW_F_IN))) + rule.fw_flg |= (IP_FW_F_OUT|IP_FW_F_IN); + + /* Sanity check interface check, but handle "via" case separately */ + if (saw_via) { + if (rule.fw_flg & IP_FW_F_IN) + rule.fw_flg |= IP_FW_F_IIFACE; + if (rule.fw_flg & IP_FW_F_OUT) + rule.fw_flg |= IP_FW_F_OIFACE; + } else if ((rule.fw_flg & IP_FW_F_OIFACE) && (rule.fw_flg & IP_FW_F_IN)) + show_usage("can't check xmit interface of incoming packets"); + + /* frag may not be used in conjunction with ports or TCP flags */ + if (rule.fw_flg & IP_FW_F_FRAG) { + if (rule.fw_tcpf || rule.fw_tcpnf) + show_usage("can't mix 'frag' and tcpflags"); + + if (rule.fw_nports) + show_usage("can't mix 'frag' and port specifications"); + } + + if (!do_quiet) + show_ipfw(&rule, 10, 10); + i = setsockopt(s, IPPROTO_IP, IP_FW_ADD, &rule, sizeof rule); + if (i) + err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_ADD"); +} + +static void +zero (ac, av) + int ac; + char **av; +{ + av++; ac--; + + if (!ac) { + /* clear all entries */ + if (setsockopt(s,IPPROTO_IP,IP_FW_ZERO,NULL,0)<0) + err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_ZERO"); + if (!do_quiet) + printf("Accounting cleared.\n"); + } else { + struct ip_fw rule; + int failed = EX_OK; + + memset(&rule, 0, sizeof rule); + while (ac) { + /* Rule number */ + if (isdigit(**av)) { + rule.fw_number = atoi(*av); av++; ac--; + if (setsockopt(s, IPPROTO_IP, + IP_FW_ZERO, &rule, sizeof rule)) { + warn("rule %u: setsockopt(%s)", rule.fw_number, + "IP_FW_ZERO"); + failed = EX_UNAVAILABLE; + } + else if (!do_quiet) + printf("Entry %d cleared\n", + rule.fw_number); + } else + show_usage("invalid rule number ``%s''", *av); + } + if (failed != EX_OK) + exit(failed); + } +} + +static int +ipfw_main(ac,av) + int ac; + char **av; +{ + + int ch; + extern int optreset; /* XXX should be declared in */ + + if ( ac == 1 ) { + show_usage(NULL); + } + + /* Set the force flag for non-interactive processes */ + do_force = !isatty(STDIN_FILENO); + + optind = optreset = 1; + while ((ch = getopt(ac, av, "afqtN")) != -1) + switch(ch) { + case 'a': + do_acct=1; + break; + case 'f': + do_force=1; + break; + case 'q': + do_quiet=1; + break; + case 't': + do_time=1; + break; + case 'N': + do_resolv=1; + break; + default: + show_usage(NULL); + } + + ac -= optind; + if (*(av+=optind)==NULL) { + show_usage("Bad arguments"); + } + + if (!strncmp(*av, "pipe", strlen(*av))) { + do_pipe = 1 ; + ac-- ; + av++ ; + } + if (!ac) { + show_usage("pipe requires arguments"); + } + /* allow argument swapping */ + if (ac > 1 && *av[0]>='0' && *av[0]<='9') { + char *p = av[0] ; + av[0] = av[1] ; + av[1] = p ; + } + if (!strncmp(*av, "add", strlen(*av))) { + add(ac,av); + } else if (do_pipe && !strncmp(*av, "config", strlen(*av))) { + config_pipe(ac,av); + } else if (!strncmp(*av, "delete", strlen(*av))) { + delete(ac,av); + } else if (!strncmp(*av, "flush", strlen(*av))) { + int do_flush = 0; + + if ( do_force || do_quiet ) + do_flush = 1; + else { + int c; + + /* Ask the user */ + printf("Are you sure? [yn] "); + do { + fflush(stdout); + c = toupper(getc(stdin)); + while (c != '\n' && getc(stdin) != '\n') + if (feof(stdin)) + return (0); + } while (c != 'Y' && c != 'N'); + printf("\n"); + if (c == 'Y') + do_flush = 1; + } + if ( do_flush ) { + if (setsockopt(s,IPPROTO_IP,IP_FW_FLUSH,NULL,0) < 0) + err(EX_UNAVAILABLE, "setsockopt(%s)", "IP_FW_FLUSH"); + if (!do_quiet) + printf("Flushed all rules.\n"); + } + } else if (!strncmp(*av, "zero", strlen(*av))) { + zero(ac,av); + } else if (!strncmp(*av, "print", strlen(*av))) { + list(--ac,++av); + } else if (!strncmp(*av, "list", strlen(*av))) { + list(--ac,++av); + } else if (!strncmp(*av, "show", strlen(*av))) { + do_acct++; + list(--ac,++av); + } else { + show_usage("Bad arguments"); + } + return 0; +} + +int +main(ac, av) + int ac; + char **av; +{ +#define MAX_ARGS 32 +#define WHITESP " \t\f\v\n\r" + char buf[BUFSIZ]; + char *a, *p, *args[MAX_ARGS], *cmd = NULL; + char linename[10]; + int i, c, qflag, pflag, status; + FILE *f = NULL; + pid_t preproc = 0; + + s = socket( AF_INET, SOCK_RAW, IPPROTO_RAW ); + if ( s < 0 ) + err(EX_UNAVAILABLE, "socket"); + + setbuf(stdout,0); + + if (ac > 1 && access(av[ac - 1], R_OK) == 0) { + qflag = pflag = i = 0; + lineno = 0; + + while ((c = getopt(ac, av, "D:U:p:q")) != -1) + switch(c) { + case 'D': + if (!pflag) + errx(EX_USAGE, "-D requires -p"); + if (i > MAX_ARGS - 2) + errx(EX_USAGE, + "too many -D or -U options"); + args[i++] = "-D"; + args[i++] = optarg; + break; + + case 'U': + if (!pflag) + errx(EX_USAGE, "-U requires -p"); + if (i > MAX_ARGS - 2) + errx(EX_USAGE, + "too many -D or -U options"); + args[i++] = "-U"; + args[i++] = optarg; + break; + + case 'p': + pflag = 1; + cmd = optarg; + args[0] = cmd; + i = 1; + break; + + case 'q': + qflag = 1; + break; + + default: + show_usage(NULL); + } + + av += optind; + ac -= optind; + if (ac != 1) + show_usage("extraneous filename arguments"); + + if ((f = fopen(av[0], "r")) == NULL) + err(EX_UNAVAILABLE, "fopen: %s", av[0]); + + if (pflag) { + /* pipe through preprocessor (cpp or m4) */ + int pipedes[2]; + + args[i] = 0; + + if (pipe(pipedes) == -1) + err(EX_OSERR, "cannot create pipe"); + + switch((preproc = fork())) { + case -1: + err(EX_OSERR, "cannot fork"); + + case 0: + /* child */ + if (dup2(fileno(f), 0) == -1 || + dup2(pipedes[1], 1) == -1) + err(EX_OSERR, "dup2()"); + fclose(f); + close(pipedes[1]); + close(pipedes[0]); + execvp(cmd, args); + err(EX_OSERR, "execvp(%s) failed", cmd); + + default: + /* parent */ + fclose(f); + close(pipedes[1]); + if ((f = fdopen(pipedes[0], "r")) == NULL) { + int savederrno = errno; + + (void)kill(preproc, SIGTERM); + errno = savederrno; + err(EX_OSERR, "fdopen()"); + } + } + } + + while (fgets(buf, BUFSIZ, f)) { + lineno++; + sprintf(linename, "Line %d", lineno); + args[0] = linename; + + if (*buf == '#') + continue; + if ((p = strchr(buf, '#')) != NULL) + *p = '\0'; + i=1; + if (qflag) args[i++]="-q"; + for (a = strtok(buf, WHITESP); + a && i < MAX_ARGS; a = strtok(NULL, WHITESP), i++) + args[i] = a; + if (i == (qflag? 2: 1)) + continue; + if (i == MAX_ARGS) + errx(EX_USAGE, "%s: too many arguments", linename); + args[i] = NULL; + + ipfw_main(i, args); + } + fclose(f); + if (pflag) { + if (waitpid(preproc, &status, 0) != -1) { + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != EX_OK) + errx(EX_UNAVAILABLE, + "preprocessor exited with status %d", + WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + errx(EX_UNAVAILABLE, + "preprocessor exited with signal %d", + WTERMSIG(status)); + } + } + } + + } else + ipfw_main(ac,av); + return EX_OK; +} diff --git a/logger.tproj/Makefile b/logger.tproj/Makefile new file mode 100644 index 0000000..c186192 --- /dev/null +++ b/logger.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = logger + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = logger.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ + h.template logger.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/logger.tproj/Makefile.postamble b/logger.tproj/Makefile.postamble new file mode 100644 index 0000000..7823726 --- /dev/null +++ b/logger.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/logger.tproj/Makefile.preamble b/logger.tproj/Makefile.preamble new file mode 100644 index 0000000..74ce95a --- /dev/null +++ b/logger.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/logger.tproj/PB.project b/logger.tproj/PB.project new file mode 100644 index 0000000..796d25c --- /dev/null +++ b/logger.tproj/PB.project @@ -0,0 +1,34 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (logger.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + m.template, + h.template, + logger.1 + ); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = logger; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/logger.tproj/h.template b/logger.tproj/h.template new file mode 100644 index 0000000..f3c1b04 --- /dev/null +++ b/logger.tproj/h.template @@ -0,0 +1,11 @@ +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import + +@interface $FILENAMESANSEXTENSION$ : NSObject +{ + +} + +@end diff --git a/logger.tproj/logger.1 b/logger.tproj/logger.1 new file mode 100644 index 0000000..3a942e8 --- /dev/null +++ b/logger.tproj/logger.1 @@ -0,0 +1,102 @@ +.\" $OpenBSD: logger.1,v 1.2 1996/06/26 05:35:58 deraadt Exp $ +.\" $NetBSD: logger.1,v 1.4 1994/12/22 06:26:59 jtc Exp $ +.\" +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)logger.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt LOGGER 1 +.Os BSD 4.3 +.Sh NAME +.Nm logger +.Nd make entries in the system log +.Sh SYNOPSIS +.Nm logger +.Op Fl is +.Op Fl f Ar file +.Op Fl p Ar pri +.Op Fl t Ar tag +.Op Ar message ... +.Sh DESCRIPTION +.Nm Logger +provides a shell command interface to the +.Xr syslog 3 +system log module. +.Pp +Options: +.Pp +.Bl -tag -width "message" +.It Fl i +Log the process id of the logger process +with each line. +.It Fl s +Log the message to standard error, as well as the system log. +.It Fl f Ar file +Log the specified file. +.It Fl p Ar pri +Enter the message with the specified priority. +The priority may be specified numerically or as a ``facility.level'' +pair. +For example, ``\-p local3.info'' logs the message(s) as +.Ar info Ns rmational +level in the +.Ar local3 +facility. +The default is ``user.notice.'' +.It Fl t Ar tag +Mark every line in the log with the specified +.Ar tag . +.It Ar message +Write the message to log; if not specified, and the +.Fl f +flag is not +provided, standard input is logged. +.El +.Pp +The +.Nm logger +utility exits 0 on success, and >0 if an error occurs. +.Sh EXAMPLES +.Bd -literal -offset indent -compact +logger System rebooted + +logger \-p local0.notice \-t HOSTIDM \-f /dev/idmc +.Ed +.Sh SEE ALSO +.Xr syslog 3 , +.Xr syslogd 8 +.Sh STANDARDS +The +.Nm logger +utility conforms to +.St -p1003.2-92 . diff --git a/logger.tproj/logger.c b/logger.tproj/logger.c new file mode 100644 index 0000000..0ec8b27 --- /dev/null +++ b/logger.tproj/logger.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include + +#define SYSLOG_NAMES +#include + +int decode __P((char *, CODE *)); +int pencode __P((char *)); +void usage __P((void)); + +/* + * logger -- read and log utility + * + * Reads from an input and arranges to write the result on the system + * log. + */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch, logflags, pri; + char *tag, buf[1024]; + + tag = NULL; + pri = LOG_NOTICE; + logflags = 0; + while ((ch = getopt(argc, argv, "f:ip:st:")) != -1) + switch((char)ch) { + case 'f': /* file to log */ + if (freopen(optarg, "r", stdin) == NULL) { + (void)fprintf(stderr, "logger: %s: %s.\n", + optarg, strerror(errno)); + exit(1); + } + break; + case 'i': /* log process id also */ + logflags |= LOG_PID; + break; + case 'p': /* priority */ + pri = pencode(optarg); + break; + case 's': /* log to standard error */ + logflags |= LOG_PERROR; + break; + case 't': /* tag */ + tag = optarg; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* setup for logging */ + openlog(tag ? tag : getlogin(), logflags, 0); + (void) fclose(stdout); + + /* log input line if appropriate */ + if (argc > 0) { + register char *p, *endp; + int len; + + for (p = buf, endp = buf + sizeof(buf) - 2; *argv;) { + len = strlen(*argv); + if (p + len > endp && p > buf) { + syslog(pri, "%s", buf); + p = buf; + } + if (len > sizeof(buf) - 1) + syslog(pri, "%s", *argv++); + else { + if (p != buf) + *p++ = ' '; + bcopy(*argv++, p, len); + *(p += len) = '\0'; + } + } + if (p != buf) + syslog(pri, "%s", buf); + } else + while (fgets(buf, sizeof(buf), stdin) != NULL) + syslog(pri, "%s", buf); + exit(0); +} + +/* + * Decode a symbolic name to a numeric value + */ +int +pencode(s) + register char *s; +{ + char *save; + int fac, lev; + + for (save = s; *s && *s != '.'; ++s); + if (*s) { + *s = '\0'; + fac = decode(save, facilitynames); + if (fac < 0) { + (void)fprintf(stderr, + "logger: unknown facility name: %s.\n", save); + exit(1); + } + *s++ = '.'; + } + else { + fac = 0; + s = save; + } + lev = decode(s, prioritynames); + if (lev < 0) { + (void)fprintf(stderr, + "logger: unknown priority name: %s.\n", save); + exit(1); + } + return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK)); +} + +int +decode(name, codetab) + char *name; + CODE *codetab; +{ + register CODE *c; + + if (isdigit(*name)) + return (atoi(name)); + + for (c = codetab; c->c_name; c++) + if (!strcasecmp(name, c->c_name)) + return (c->c_val); + + return (-1); +} + +void +usage() +{ + (void)fprintf(stderr, + "logger: [-is] [-f file] [-p pri] [-t tag] [ message ... ]\n"); + exit(1); +} diff --git a/logger.tproj/m.template b/logger.tproj/m.template new file mode 100644 index 0000000..1216fe5 --- /dev/null +++ b/logger.tproj/m.template @@ -0,0 +1,18 @@ +$$ Lines starting with $$ are not inserted into newly created files +$$ The following substitutions are made: +$$ +$$ $FILENAME$ e.g. foo.m +$$ $FILENAMESANSEXTENSION$ e.g. foo +$$ $DIRECTORY$ e.g. /tmp/MyNewApp +$$ $PROJECTNAME$ e.g. MyNewApp +$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj +$$ $USERNAME$ e.g. mwagner +$$ $DATE$ e.g. Jan-1-1994 +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import "$FILENAMESANSEXTENSION$.h" + +@implementation $FILENAMESANSEXTENSION$ + +@end diff --git a/makedbm.tproj/Makefile b/makedbm.tproj/Makefile new file mode 100644 index 0000000..143e661 --- /dev/null +++ b/makedbm.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = makedbm + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = db.h ypdb.h ypdef.h + +CFILES = db.c makedbm.c ypdb.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble makedbm.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/makedbm.tproj/Makefile.postamble b/makedbm.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/makedbm.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/makedbm.tproj/Makefile.preamble b/makedbm.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/makedbm.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/makedbm.tproj/PB.project b/makedbm.tproj/PB.project new file mode 100644 index 0000000..1c1cc6f --- /dev/null +++ b/makedbm.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (db.h, ypdb.h, ypdef.h); + OTHER_LIBS = (); + OTHER_LINKED = (db.c, makedbm.c, ypdb.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, makedbm.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = makedbm; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/makedbm.tproj/db.c b/makedbm.tproj/db.c new file mode 100644 index 0000000..9d5396d --- /dev/null +++ b/makedbm.tproj/db.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: db.c,v 1.1 1997/07/22 10:52:59 maja Exp $ */ + +/* + * Copyright (c) 1997 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: db.c,v 1.1 1997/07/22 10:52:59 maja Exp $"; +#endif + +#include +#include +#include +#include +#include +#include "db.h" +#include "ypdb.h" + +/* + * This module was created to be able to read database files created + * by sendmail -bi. + */ + +int db_hash_list_database(database) +char *database; +{ + DB *db; + int status; + DBT key, val; + char path[MAXPATHLEN]; + + snprintf(path, sizeof(path), "%s%s", database, ".db"); + + db = dbopen(path, O_RDONLY, 0, DB_HASH, NULL); + if (db != NULL) { + status = db->seq(db, &key, &val, R_FIRST); + while (status == 0) { + printf("%*.*s %*.*s\n", + key.size-1, key.size-1, key.data, + val.size-1, val.size-1, val.data); + status = db->seq(db, &key, &val, R_NEXT); + } + db->close(db); + return(1); + } + return(0); +} + diff --git a/makedbm.tproj/db.h b/makedbm.tproj/db.h new file mode 100644 index 0000000..bbcf1a1 --- /dev/null +++ b/makedbm.tproj/db.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: db.h,v 1.1 1997/07/22 10:52:59 maja Exp $ */ + +/* + * Copyright (c) 1997 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _MAKEDBM_DB_H_ +#define _MAKEDBM_DB_H_ + +__BEGIN_DECLS +int db_hash_list_database __P((char *)); +__END_DECLS + +#endif /* !_MAKEDBM_DB_H_ */ + + diff --git a/makedbm.tproj/makedbm.8 b/makedbm.tproj/makedbm.8 new file mode 100644 index 0000000..151d29f --- /dev/null +++ b/makedbm.tproj/makedbm.8 @@ -0,0 +1,97 @@ +.\" $OpenBSD: makedbm.8,v 1.5 1997/07/22 10:53:00 maja Exp $ +.\" Copyright (c) 1994-97 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd July 19, 1994 +.Dt MAKEDBM 8 +.Os +.Sh NAME +.Nm makedbm +.Nd create a YP database +.Sh SYNOPSIS +.Nm makedbm +.Fl u Ar file +.Nm makedbm +.Fl U Ar file +.Nm makedbm +.Op Fl bls +.Op Fl i Ar yp_input_file +.Op Fl o Ar yp_output_file +.Op Fl d Ar yp_domain_name +.Op Fl m Ar yp_master_name +.Ar infile +.Ar outfile +.Sh DESCRIPTION +.Nm Makedbm +is the utiliy in YP that creates the database file containing the YP map. +The databse format is a slightly modified version of ndbm. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl u +Dump a database to standard output. +.It Fl U +Same as +.Fl u +but also try +.Xr db 3 +hash format. +.It Fl b +Interdomain. Include an entry in the database informing a YP server to use +DNS to get information about unknown hosts. This option will only have +effect on the two maps hosts.byname and hosts.byaddr. +.It Fl l +Lowercase. Convert all keys to lower case before adding them to the YP +database. +.It Fl s +Secure map. Include an entry in the database informing +.Xr ypxfr 8 +and +.Xr ypserv 8 +that the YP map is going to be handled as secure. +.It Fl i Ar yp_input_file +Include an entry the in the map with the key YP_INPUT_FILE and the argument +as value. +.It Fl o Ar yp_output_file +Include an entry the in the map with the key YP_OUTPUT_FILE and the argument +as value. +.It Fl d Ar yp_domain_name +Include an entry the in the map with the key YP_DOMAIN_NAME and the argument +as value. +.It Fl m Ar yp_master_name +Include an entry the in the map with the key YP_MASTER_NAME and the argument +as value. +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr db 3 , +.Xr ypxfr 8 , +.Xr ypserv 8 +.Sh AUTHOR +Mats O Jansson diff --git a/makedbm.tproj/makedbm.c b/makedbm.tproj/makedbm.c new file mode 100644 index 0000000..8d2f73e --- /dev/null +++ b/makedbm.tproj/makedbm.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: makedbm.c,v 1.9 1997/08/18 03:11:34 millert Exp $ */ + +/* + * Copyright (c) 1994-97 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: makedbm.c,v 1.9 1997/08/18 03:11:34 millert Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ypdb.h" +#include "ypdef.h" +#include "db.h" + +extern char *__progname; /* from crt0.o */ + +/* + * Read one line + */ + +static int read_line(fp, buf, size) + FILE *fp; + char *buf; + int size; +{ + int done; + + done = 0; + + do { + while (fgets(buf, size, fp)) { + int len = strlen(buf); + done += len; + if (len > 1 && buf[len-2] == '\\' && + buf[len-1] == '\n') { + int ch; + buf += len - 2; + size -= len - 2; + *buf = '\n'; buf[1] = '\0'; + + /* Skip leading white space on next line */ + while ((ch = getc(fp)) != EOF && + isascii(ch) && isspace(ch)) + ; + (void) ungetc(ch, fp); + } else { + return done; + } + } + } while (size > 0 && !feof(fp)); + + return done; +} + +void +add_record(db, str1, str2, check) + DBM *db; + char *str1, *str2; + int check; +{ + datum key,val; + int status; + + key.dptr = str1; + key.dsize = strlen(str1); + + if (check) { + val = ypdb_fetch(db,key); + + if (val.dptr != NULL) + return; /* already there */ + + } + + val.dptr = str2; + val.dsize = strlen(str2); + status = ypdb_store(db, key, val, YPDB_INSERT); + + if (status != 0) { + printf("%s: problem storing %s %s\n",__progname,str1,str2); + exit(1); + } +} + +static char * +file_date(filename) + char *filename; +{ + struct stat finfo; + static char datestr[11]; + int status; + + if (strcmp(filename,"-") == 0) { + sprintf(datestr, "%010d", time(0)); + } else { + status = stat(filename, &finfo); + if (status < 0) { + fprintf(stderr, "%s: can't stat %s\n", __progname, filename); + exit(1); + } + sprintf(datestr, "%010d", finfo.st_mtime); + } + + return datestr; +} + +void +list_database(database,Uflag) + char *database; + int Uflag; +{ + DBM *db; + datum key,val; + + db = ypdb_open(database, O_RDONLY, 0444); + + if (db == NULL) { + + if (Uflag != 0) { + + if (db_hash_list_database(database)) return; + + } + + + fprintf(stderr, "%s: can't open database %s\n", __progname, database); + exit(1); + } + + key = ypdb_firstkey(db); + + while (key.dptr != NULL) { + val = ypdb_fetch(db,key); + printf("%*.*s %*.*s\n", + key.dsize, key.dsize, key.dptr, + val.dsize, val.dsize, val.dptr); + key = ypdb_nextkey(db); + } + + ypdb_close(db); + +} + +void + +create_database(infile,database, + yp_input_file,yp_output_file, + yp_master_name,yp_domain_name, + bflag, lflag, sflag) + char *infile, *database; + char *yp_input_file, *yp_output_file; + char *yp_master_name, *yp_domain_name; + int bflag, lflag, sflag; +{ + FILE *data_file; + char data_line[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ + char myname[MAXHOSTNAMELEN]; + int line_no = 0; + int len; + char *p,*k,*v; + char *slash; + DBM *new_db; + static char mapname[] = "ypdbXXXXXXXXXX"; + char db_mapname[MAXPATHLEN],db_outfile[MAXPATHLEN], + db_tempname[MAXPATHLEN]; + char empty_str[] = ""; + + if (strcmp(infile,"-") == 0) { + data_file = stdin; + } else { + data_file = fopen(infile, "r"); + if (errno != 0) { + (void)fprintf(stderr,"%s: ",__progname); + perror(infile); + exit(1); + } + } + + if (strlen(database) + strlen(YPDB_SUFFIX) > MAXPATHLEN) { + fprintf(stderr,"%s: %s: file name too long\n", + __progname, database); + exit(1); + } + snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX); + + slash = strrchr(database, '/'); + if (slash != NULL) + slash[1] = 0; /* truncate to dir */ + else + *database = 0; /* elminate */ + + /* note: database is now directory where map goes ! */ + + if (strlen(database) + strlen(mapname) + + strlen(YPDB_SUFFIX) > MAXPATHLEN) { + fprintf(stderr,"%s: %s: directory name too long\n", + __progname, database); + exit(1); + } + + snprintf(db_tempname, sizeof(db_tempname), "%s%s", database, + mapname); + mktemp(db_tempname); + snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname, + YPDB_SUFFIX); + + new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444); + + while (read_line(data_file,data_line,sizeof(data_line))) { + + line_no++; + len = strlen(data_line); + + /* Check if we have the whole line */ + + if (data_line[len-1] != '\n') { + fprintf(stderr, "line %d in \"%s\" is too long", + line_no, infile); + } else { + data_line[len-1] = '\0'; + } + + p = (char *) &data_line; + + k = p; /* save start of key */ + while (!isspace(*p)) { /* find first "space" */ + if (lflag && isupper(*p)) /* if force lower case */ + *p = tolower(*p); /* fix it */ + p++; + }; + while (isspace(*p)) { /* replace space with */ + *p = '\0'; + p++; + }; + + v = p; /* save start of value */ + while(*p != '\0') { p++; }; /* find end of string */ + + add_record(new_db, k, v, TRUE); /* save record */ + + } + + if (strcmp(infile,"-") != 0) { + (void) fclose(data_file); + } + + add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE); + + if (yp_input_file) { + add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE); + } + + if (yp_output_file) { + add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE); + } + + if (yp_master_name) { + add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE); + } else { + gethostname(myname, sizeof(myname) - 1); + add_record(new_db, YP_MASTER_KEY, myname, FALSE); + } + + if (yp_domain_name) { + add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE); + } + + if (bflag) { + add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE); + } + + if (sflag) { + add_record(new_db, YP_SECURE_KEY, empty_str, FALSE); + } + + ypdb_close(new_db); + if (rename(db_mapname,db_outfile) < 0) { + perror("rename"); + fprintf(stderr,"rename %s -> %s failed!\n", db_mapname, + db_outfile); + exit(1); + } + +} + +int +main (argc,argv) + int argc; + char *argv[]; +{ + int aflag, uflag, bflag, lflag, sflag, Uflag; + char *yp_input_file, *yp_output_file; + char *yp_master_name,*yp_domain_name; + char *infile,*outfile; + int usage = 0; + int ch; + + extern int optind; + + yp_input_file = yp_output_file = NULL; + yp_master_name = yp_domain_name = NULL; + aflag = uflag = bflag = lflag = sflag = Uflag = 0; + infile = outfile = NULL; + + while ((ch = getopt(argc, argv, "Ublsui:o:m:d:")) != -1) + switch (ch) { + case 'U': + uflag++; + Uflag++; + break; + case 'b': + bflag++; + aflag++; + break; + case 'l': + lflag++; + aflag++; + break; + case 's': + sflag++; + aflag++; + break; + case 'i': + yp_input_file = argv[optind]; + aflag++; + break; + case 'o': + yp_output_file = argv[optind]; + aflag++; + break; + case 'm': + yp_master_name = argv[optind]; + aflag++; + break; + case 'd': + yp_domain_name = argv[optind]; + aflag++; + break; + case 'u': + uflag++; + break; + default: + usage++; + break; + } + + if ((uflag != 0) && (aflag != 0)) { + usage++; + } else { + + if (uflag != 0) { + if (argc == (optind + 1)) { + infile = argv[optind]; + } else { + usage++; + } + } else { + if (argc == (optind + 2)) { + infile = argv[optind]; + outfile = argv[optind+1]; + } else { + usage++; + } + } + } + + if (usage) { + fprintf(stderr,"%s%s%s", + "usage:\tmakedbm [-u|-U] file\n\tmakedbm [-bls]", + " [-i YP_INPUT_FILE] [-o YP_OUTPUT_FILE]\n\t\t", + "[-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME] infile outfile\n"); + exit(1); + } + + if (uflag != 0) { + list_database(infile,Uflag); + } else { + create_database(infile,outfile, + yp_input_file,yp_output_file, + yp_master_name,yp_domain_name, + bflag, lflag, sflag); + } + + return(0); + +} diff --git a/makedbm.tproj/ypdb.c b/makedbm.tproj/ypdb.c new file mode 100644 index 0000000..c9bd178 --- /dev/null +++ b/makedbm.tproj/ypdb.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "ypdb.h" + +#ifdef YPDB_PATCH +extern DBM *__hash_open(); +#else +extern DBM *__bt_open(); +#endif + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +#else + BTREEINFO info; + char path[MAXPATHLEN]; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + db = (DBM *)__bt_open(path, flags, mode, &info, 0); + return (db); +#endif +} + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open_suf(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + return ((DBM *)__hash_open(file, flags, mode, &info, 0)); +#else + BTREEINFO info; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + db = (DBM *)__bt_open(file, flags, mode, &info, 0); + return (db); +#endif +} + +extern void +ypdb_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_firstkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_nextkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_setkey(db, key) + DBM *db; + datum key; +{ + int status; + datum retdata; +#ifdef YPDB_PATCH + datum retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + while ((retkey.dptr != NULL) && + ((retkey.dsize != key.dsize) || + (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) { + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + }; + return (retkey); +#else + status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR); + if (status) + key.dptr = NULL; + return (key); +#endif +} + +/* + * Returns: + * 0 on success + * <0 failure + */ + +int +ypdb_delete(db, key) + DBM *db; + datum key; +{ + int status; + + status = (db->del)(db, (DBT *)&key, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if YPDB_INSERT and entry exists + */ + +int +ypdb_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0)); +} + diff --git a/makedbm.tproj/ypdb.h b/makedbm.tproj/ypdb.h new file mode 100644 index 0000000..9afbad5 --- /dev/null +++ b/makedbm.tproj/ypdb.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDB_H_ +#define _YPDB_H_ + +#ifndef _DB_H_ +#include +#endif + +#define YPDB_SUFFIX ".db" + +/* Flags to ypdb_store(). */ +#define YPDB_INSERT 0 +#define YPDB_REPLACE 1 + +#ifndef DATUM +typedef struct { + char *dptr; + int dsize; +} datum; +#define DATUM +#endif + +typedef DB DBM; + +__BEGIN_DECLS +void ypdb_close __P((DBM *)); +datum ypdb_fetch __P((DBM *, datum)); +datum ypdb_firstkey __P((DBM *)); +datum ypdb_nextkey __P((DBM *)); +datum ypdb_setkey __P((DBM *, datum)); +DBM *ypdb_open __P((const char *, int, int)); +DBM *ypdb_open_suf __P((const char *, int, int)); +int ypdb_store __P((DBM *, datum, datum, int)); +__END_DECLS + +#endif /* !_YPDB_H_ */ diff --git a/makedbm.tproj/ypdef.h b/makedbm.tproj/ypdef.h new file mode 100644 index 0000000..89970d7 --- /dev/null +++ b/makedbm.tproj/ypdef.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDEF_H_ +#define _YPDEF_H_ + +#define YP_DB_PATH "/var/yp" +#define YP_LAST_KEY "YP_LAST_MODIFIED" +#define YP_LAST_LEN (sizeof(YP_LAST_KEY)-1) +#define YP_INPUT_KEY "YP_INPUT_FILE" +#define YP_INPUT_LEN (sizeof(YP_INPUT_KEY)-1) +#define YP_OUTPUT_KEY "YP_OUTPUT_FILE" +#define YP_OUTPUT_LEN (sizeof(YP_OUTPUT_KEY)-1) +#define YP_MASTER_KEY "YP_MASTER_NAME" +#define YP_MASTER_LEN (sizeof(YP_MASTER_KEY)-1) +#define YP_DOMAIN_KEY "YP_DOMAIN_NAME" +#define YP_DOMAIN_LEN (sizeof(YP_DOMAIN_KEY)-1) +#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN" +#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1) +#define YP_SECURE_KEY "YP_SECURE" +#define YP_SECURE_LEN (sizeof(YP_SECURE_KEY)-1) + +#define MAX_LAST_LEN 10 +#define MAX_MASTER_LEN 255 +#define YP_HOSTNAME "hosts.byname" +#define YP_HOSTADDR "hosts.byaddr" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define YPXFR_PROC "/usr/sbin/ypxfr" +#define YPPUSH_PROC "/usr/sbin/yppush" +#define YPSERV_PID_PATH "/var/run/ypserv.pid" +#define YP_SECURENET_FILE "/var/yp/securenet" + +#endif /* !_YPDEF_H_ */ diff --git a/natd.tproj/Makefile b/natd.tproj/Makefile new file mode 100644 index 0000000..ad7ef52 --- /dev/null +++ b/natd.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the Apple Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = natd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = natd.h + +CFILES = icmp.c natd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble natd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /Library/Executables +PDO_UNIX_INSTALLDIR = /bin +LIBS = -lalias +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(JDKBINDIR)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/natd.tproj/Makefile.postamble b/natd.tproj/Makefile.postamble new file mode 100644 index 0000000..acc4f20 --- /dev/null +++ b/natd.tproj/Makefile.postamble @@ -0,0 +1,104 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGES: langages in which the project is written (default "English") +# English_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +install-man-page: + install -d $(DSTROOT)/usr/share/man/man8 + install -c -m 444 natd.8 $(DSTROOT)/usr/share/man/man8/natd.8 + diff --git a/natd.tproj/Makefile.preamble b/natd.tproj/Makefile.preamble new file mode 100644 index 0000000..a4606c6 --- /dev/null +++ b/natd.tproj/Makefile.preamble @@ -0,0 +1,140 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. For library projects you should +# set this to something like /Developer/Headers/$(NAME). Do not set +# this variable for framework projects unless you do not want the +# header files included in the framework. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. This defaults to +# DYNAMIC. +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSIONS: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Uncomment to suppress generation of a KeyValueCoding index when installing +# frameworks (This index is used by WOB and IB to determine keys available +# for an object). Set to YES by default. +# PREINDEX_FRAMEWORK = NO + +# Change this definition to install projects somewhere other than the +# standard locations. NEXT_ROOT defaults to "C:/Apple" on Windows systems +# and "" on other systems. +DSTROOT = $(HOME) + +AFTER_INSTALL += install-man-page + diff --git a/natd.tproj/PB.project b/natd.tproj/PB.project new file mode 100644 index 0000000..a64fa2f --- /dev/null +++ b/natd.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (natd.h); + OTHER_LIBS = (alias); + OTHER_LINKED = (icmp.c, natd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, natd.8); + }; + LANGUAGE = English; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(JDKBINDIR)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = natd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = /Library/Executables; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/natd.tproj/icmp.c b/natd.tproj/icmp.c new file mode 100644 index 0000000..10d3bda --- /dev/null +++ b/natd.tproj/icmp.c @@ -0,0 +1,126 @@ +/* + * natd - Network Address Translation Daemon for FreeBSD. + * + * This software is provided free of charge, with no + * warranty of any kind, either expressed or implied. + * Use at your own risk. + * + * You may copy, modify and distribute this software (icmp.c) freely. + * + * Ari Suutari + * + * $Id: icmp.c,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $ + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include "natd.h" + +int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu) +{ + char icmpBuf[IP_MAXPACKET]; + struct ip* ip; + struct icmp* icmp; + int icmpLen; + int failBytes; + int failHdrLen; + struct sockaddr_in addr; + int wrote; + struct in_addr swap; +/* + * Don't send error if packet is + * not the first fragment. + */ + if (ntohs (failedDgram->ip_off) & ~(IP_MF | IP_DF)) + return 0; +/* + * Dont respond if failed datagram is ICMP. + */ + if (failedDgram->ip_p == IPPROTO_ICMP) + return 0; +/* + * Start building the message. + */ + ip = (struct ip*) icmpBuf; + icmp = (struct icmp*) (icmpBuf + sizeof (struct ip)); +/* + * Complete ICMP part. + */ + icmp->icmp_type = ICMP_UNREACH; + icmp->icmp_code = ICMP_UNREACH_NEEDFRAG; + icmp->icmp_cksum = 0; + icmp->icmp_void = 0; + icmp->icmp_nextmtu = htons (mtu); +/* + * Copy header + 64 bits of original datagram. + */ + failHdrLen = (failedDgram->ip_hl << 2); + failBytes = failedDgram->ip_len - failHdrLen; + if (failBytes > 8) + failBytes = 8; + + failBytes += failHdrLen; + icmpLen = ICMP_MINLEN + failBytes; + + memcpy (&icmp->icmp_ip, failedDgram, failBytes); +/* + * Calculate checksum. + */ + icmp->icmp_cksum = PacketAliasInternetChecksum ((u_short*) icmp, + icmpLen); +/* + * Add IP header using old IP header as template. + */ + memcpy (ip, failedDgram, sizeof (struct ip)); + + ip->ip_v = 4; + ip->ip_hl = 5; + ip->ip_len = htons (sizeof (struct ip) + icmpLen); + ip->ip_p = IPPROTO_ICMP; + ip->ip_tos = 0; + + swap = ip->ip_dst; + ip->ip_dst = ip->ip_src; + ip->ip_src = swap; + + PacketAliasIn ((char*) ip, IP_MAXPACKET); + + addr.sin_family = AF_INET; + addr.sin_addr = ip->ip_dst; + addr.sin_port = 0; +/* + * Put packet into processing queue. + */ + wrote = sendto (sock, + icmp, + icmpLen, + 0, + (struct sockaddr*) &addr, + sizeof addr); + + if (wrote != icmpLen) + Warn ("Cannot send ICMP message."); + + return 1; +} + + diff --git a/natd.tproj/natd.8 b/natd.tproj/natd.8 new file mode 100644 index 0000000..1d1cb7f --- /dev/null +++ b/natd.tproj/natd.8 @@ -0,0 +1,426 @@ +.\" manual page [] for natd 1.4 +.\" $Id: natd.8,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $ +.Dd 15 April 1997 +.Os FreeBSD +.Dt NATD 8 +.Sh NAME +.Nm natd +.Nd +Network Address Translation Daemon +.Sh SYNOPSIS +.Nm +.Op Fl ldsmvu +.Op Fl dynamic +.Op Fl i Ar inport +.Op Fl o Ar outport +.Op Fl p Ar port +.Op Fl a Ar address +.Op Fl n Ar interface +.Op Fl f Ar configfile + +.Nm +.Op Fl log +.Op Fl deny_incoming +.Op Fl log_denied +.Op Fl use_sockets +.Op Fl same_ports +.Op Fl verbose +.Op Fl log_facility Ar facility_name +.Op Fl unregistered_only +.Op Fl dynamic +.Op Fl inport Ar inport +.Op Fl outport Ar outport +.Op Fl port Ar port +.Op Fl alias_address Ar address +.Op Fl interface Ar interface +.Op Fl config Ar configfile +.Op Fl redirect_port Ar linkspec +.Op Fl redirect_address Ar localIP publicIP +.Op Fl reverse +.Op Fl proxy_only +.Op Fl proxy_rule Ar proxyspec +.Op Fl pptpalias Ar localIP + +.Sh DESCRIPTION +This program provides a Network Address Translation facility for use +with +.Xr divert 4 +sockets under FreeBSD. It is intended for use with NICs - if you want +to do NAT on a PPP link, use the -alias switch to +.Xr ppp 8 . + +.Pp +.Nm Natd +normally runs in the background as a daemon. It is passed raw IP packets +as they travel into and out of the machine, and will possibly change these +before re-injecting them back into the IP packet stream. + +.Pp +.Nm Natd +changes all packets destined for another host so that their source +IP number is that of the current machine. For each packet changed +in this manner, an internal table entry is created to record this +fact. The source port number is also changed to indicate the +table entry applying to the packet. Packets that are received with +a target IP of the current host are checked against this internal +table. If an entry is found, it is used to determine the correct +target IP number and port to place in the packet. + +.Pp +The following command line options are available. +.Bl -tag -width Fl + +.It Fl log | l +Log various aliasing statistics and information to the file +.Pa /var/log/alias.log . +This file is truncated each time natd is started. + +.It Fl deny_incoming | d +Reject packets destined for the current IP number that have no entry +in the internal translation table. + +.It Fl log_denied +Log denied incoming packets via syslog (see also log_facility) + +.It Fl log_facility Ar facility_name +Use specified log facility when logging information via syslog. +Facility names are as in +.Xr syslog.conf 5 + +.It Fl use_sockets | s +Allocate a +.Xr socket 2 +in order to establish an FTP data or IRC DCC send connection. This +option uses more system resources, but guarantees successful connections +when port numbers conflict. + +.It Fl same_ports | m +Try to keep the same port number when altering outgoing packets. +With this option, protocols such as RPC will have a better chance +of working. If it is not possible to maintain the port number, it +will be silently changed as per normal. + +.It Fl verbose | v +Don't call +.Xr fork 2 +or +.Xr daemon 3 +on startup. Instead, stay attached to the controling terminal and +display all packet alterations to the standard output. This option +should only be used for debugging purposes. + +.It Fl unregistered_only | u +Only alter outgoing packets with an unregistered source address. +According to rfc 1918, unregistered source addresses are 10.0.0.0/8, +172.16.0.0/12 and 192.168.0.0/16. + +.It Fl redirect_port Ar proto targetIP:targetPORT [aliasIP:]aliasPORT [remoteIP[:remotePORT]] +Redirect incoming connections arriving to given port to another host and port. +Proto is either tcp or udp, targetIP is the desired target IP +number, targetPORT is the desired target PORT number, aliasPORT +is the requested PORT number and aliasIP is the aliasing address. +RemoteIP and remotePORT can be used to specify the connection +more accurately if necessary. +For example, the argument + +.Ar tcp inside1:telnet 6666 + +means that tcp packets destined for port 6666 on this machine will +be sent to the telnet port on the inside1 machine. + +.It Fl redirect_address Ar localIP publicIP +Redirect traffic for public IP address to a machine on the local +network. This function is known as "static NAT". Normally static NAT +is useful if your ISP has allocated a small block of IP addresses to you, +but it can even be used in the case of single address: + + redirect_address 10.0.0.8 0.0.0.0 + +The above command would redirect all incoming traffic +to machine 10.0.0.8. + +If several address aliases specify the same public address +as follows + + redirect_address 192.168.0.2 public_addr + redirect_address 192.168.0.3 public_addr + redirect_address 192.168.0.4 public_addr + +the incoming traffic will be directed to the last +translated local address (192.168.0.4), but outgoing +traffic to the first two addresses will still be aliased +to specified public address. + +.It Fl dynamic +If the +.Fl n +or +.Fl interface +option is used, +.Nm +will monitor the routing socket for alterations to the +.Ar interface +passed. If the interfaces IP number is changed, +.Nm +will dynamically alter its concept of the alias address. + +.It Fl i | inport Ar inport +Read from and write to +.Ar inport , +treating all packets as packets coming into the machine. + +.It Fl o | outport Ar outport +Read from and write to +.Ar outport , +treating all packets as packets going out of the machine. + +.It Fl p | port Ar port +Read from and write to +.Ar port , +distinguishing packets as incoming our outgoing using the rules specified in +.Xr divert 4 . +If +.Ar port +is not numeric, it is searched for in the +.Pa /etc/services +database using the +.Xr getservbyname 3 +function. If this flag is not specified, the divert port named natd will +be used as a default. An example entry in the +.Pa /etc/services +database would be: + + natd 8668/divert # Network Address Translation socket + +Refer to +.Xr services 5 +for further details. + +.It Fl a | alias_address Ar address +Use +.Ar address +as the alias address. If this option is not specified, the +.Fl n +or +.Fl interface +option must be used. The specified address should be the address assigned +to the public network interface. +.Pp +All data passing out through this addresses interface will be rewritten +with a source address equal to +.Ar address . +All data arriving at the interface from outside will be checked to +see if it matches any already-aliased outgoing connection. If it does, +the packet is altered accordingly. If not, all +.Fl redirect_port +and +.Fl redirect_address +assignments are checked and actioned. If no other action can be made, +and if +.Fl deny_incoming +is not specified, the packet is delivered to the local machine and port +as specified in the packet. + +.It Fl n | interface Ar interface +Use +.Ar interface +to determine the alias address. If there is a possibility that the +IP number associated with +.Ar interface +may change, the +.Fl dynamic +flag should also be used. If this option is not specified, the +.Fl a +or +.Fl alias_address +flag must be used. +.Pp +The specified +.Ar interface +must be the public network interface. +.It Fl f | config Ar configfile +Read configuration from +.Ar configfile . +.Ar Configfile +contains a list of options, one per line in the same form as the +long form of the above command line flags. For example, the line + + alias_address 158.152.17.1 + +would specify an alias address of 158.152.17.1. Options that don't +take an argument are specified with an option of +.Ar yes +or +.Ar no +in the configuration file. For example, the line + + log yes + +is synonomous with +.Fl log . +Empty lines and lines beginning with '#' are ignored. + +.It Fl reverse +Reverse operation of natd. This can be useful in some +transparent proxying situations when outgoing traffic +is redirected to the local machine and natd is running on the +incoming interface (it usually runs on the outgoing interface). + +.It Fl proxy_only +Force natd to perform transparent proxying +only. Normal address translation is not performed. + +.It Fl proxy_rule Ar [type encode_ip_hdr|encode_tcp_stream] port xxxx server a.b.c.d:yyyy +Enable transparent proxying. Packets with the given port going through this +host to any other host are redirected to the given server and port. +Optionally, the original target address can be encoded into the packet. Use +.Dq encode_ip_hdr +to put this information into the IP option field or +.Dq encode_tcp_stream +to inject the data into the beginning of the TCP stream. + +.It Fl pptpalias Ar localIP +Allow PPTP packets to go to the defined localIP address. PPTP is a VPN or secure +IP tunneling technology being developed primarily by Microsoft. For its encrypted traffic, +it uses an old IP encapsulation protocol called GRE (47). This +natd option will translate any traffic of this protocol to a +single, specified IP address. This would allow either one client or one server +to be serviced with natd. If you are setting up a server, don't forget to allow the TCP traffic +for the PPTP setup. For a client or server, you must allow GRE (protocol 47) if you have firewall lists active. + +.El + +.Sh RUNNING NATD +The following steps are necessary before attempting to run +.Nm natd : + +.Bl -enum +.It +Get FreeBSD version 2.2 or higher. Versions before this do not support +.Xr divert 4 +sockets. + +.It +Build a custom kernel with the following options: + + options IPFIREWALL + options IPDIVERT + +Refer to the handbook for detailed instructions on building a custom +kernel. + +.It +Ensure that your machine is acting as a gateway. This can be done by +specifying the line + + gateway_enable=YES + +in +.Pa /etc/rc.conf , +or using the command + + sysctl -w net.inet.ip.forwarding=1 + +.It +If you wish to use the +.Fl n +or +.Fl interface +flags, make sure that your interface is already configured. If, for +example, you wish to specify tun0 as your +.Ar interface , +and you're using +.Xr ppp 8 +on that interface, you must make sure that you start +.Nm ppp +prior to starting +.Nm natd . + +.It +Create an entry in +.Pa /etc/services : + + natd 8668/divert # Network Address Translation socket + +This gives a default for the +.Fl p +or +.Fl port +flag. + +.El +.Pp +Running +.Nm +is fairly straight forward. The line + + natd -interface ed0 + +should suffice in most cases (substituting the correct interface name). Once +.Nm +is running, you must ensure that traffic is diverted to natd: + +.Bl -enum +.It +You will need to adjust the +.Pa /etc/rc.firewall +script to taste. If you're not interested in having a firewall, the +following lines will do: + + /sbin/ipfw -f flush + /sbin/ipfw add divert natd all from any to any via ed0 + /sbin/ipfw add pass all from any to any + +The second line depends on your interface (change ed0 as appropriate) +and assumes that you've updated +.Pa /etc/services +with the natd entry as above. If you specify real firewall rules, it's +best to specify line 2 at the start of the script so that +.Nm +sees all packets before they are dropped by the firewall. The firewall +rules will be run again on each packet after translation by +.Nm natd , +minus any divert rules. + +.It +Enable your firewall by setting + + firewall_enable=YES + +in +.Pa /etc/rc.conf . +This tells the system startup scripts to run the +.Pa /etc/rc.firewall +script. If you don't wish to reboot now, just run this by hand from the +console. NEVER run this from a virtual session unless you put it into +the background. If you do, you'll lock yourself out after the flush +takes place, and execution of +.Pa /etc/rc.firewall +will stop at this point - blocking all accesses permanently. Running +the script in the background should be enough to prevent this disaster. + +.El + +.Sh SEE ALSO +.Xr getservbyname 2 , +.Xr socket 2 , +.Xr divert 4 , +.Xr services 5 , +.Xr ipfw 8 + +.Sh AUTHORS +This program is the result of the efforts of many people at different +times: + +.An Archie Cobbs Aq archie@whistle.com +(divert sockets) +.An Charles Mott Aq cmott@srv.net +(packet aliasing) +.An Eivind Eklund Aq perhaps@yes.no +(IRC support & misc additions) +.An Ari Suutari Aq suutari@iki.fi +(natd) +.An Dru Nelson Aq dnelson@redwoodsoft.com +(PPTP support) +.An Brian Somers Aq brian@awfulhak.org +(glue) diff --git a/natd.tproj/natd.c b/natd.tproj/natd.c new file mode 100644 index 0000000..bbb8678 --- /dev/null +++ b/natd.tproj/natd.c @@ -0,0 +1,1578 @@ +/* + * natd - Network Address Translation Daemon for FreeBSD. + * + * This software is provided free of charge, with no + * warranty of any kind, either expressed or implied. + * Use at your own risk. + * + * You may copy, modify and distribute this software (natd.c) freely. + * + * Ari Suutari + * + * $Id: natd.c,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $ + */ + +#define SYSLOG_NAMES + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "natd.h" + +/* + * Default values for input and output + * divert socket ports. + */ + +#define DEFAULT_SERVICE "natd" + +/* + * Definition of a port range, and macros to deal with values. + * FORMAT: HI 16-bits == first port in range, 0 == all ports. + * LO 16-bits == number of ports in range + * NOTES: - Port values are not stored in network byte order. + */ + +typedef u_long port_range; + +#define GETLOPORT(x) ((x) >> 0x10) +#define GETNUMPORTS(x) ((x) & 0x0000ffff) +#define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x))) + +/* Set y to be the low-port value in port_range variable x. */ +#define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10)) + +/* Set y to be the number of ports in port_range variable x. */ +#define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y)) + +/* + * Function prototypes. + */ + +static void DoAliasing (int fd, int direction); +static void DaemonMode (void); +static void HandleRoutingInfo (int fd); +static void Usage (void); +static char* FormatPacket (struct ip*); +static void PrintPacket (struct ip*); +static void SyslogPacket (struct ip*, int priority, const char *label); +static void SetAliasAddressFromIfName (char* ifName); +static void InitiateShutdown (int); +static void Shutdown (int); +static void RefreshAddr (int); +static void ParseOption (const char* option, const char* parms, int cmdLine); +static void ReadConfigFile (const char* fileName); +static void SetupPortRedirect (const char* parms); +static void SetupAddressRedirect (const char* parms); +static void SetupPptpAlias (const char* parms); +static void StrToAddr (const char* str, struct in_addr* addr); +static u_short StrToPort (const char* str, const char* proto); +static int StrToPortRange (const char* str, const char* proto, port_range *portRange); +static int StrToProto (const char* str); +static int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange); +static void ParseArgs (int argc, char** argv); +static void FlushPacketBuffer (int fd); + +/* + * Globals. + */ + +static int verbose; +static int background; +static int running; +static int assignAliasAddr; +static char* ifName; +static int ifIndex; +static u_short inPort; +static u_short outPort; +static u_short inOutPort; +static struct in_addr aliasAddr; +static int dynamicMode; +static int ifMTU; +static int aliasOverhead; +static int icmpSock; +static char packetBuf[IP_MAXPACKET]; +static int packetLen; +static struct sockaddr_in packetAddr; +static int packetSock; +static int packetDirection; +static int dropIgnoredIncoming; +static int logDropped; +static int logFacility; + +int main (int argc, char** argv) +{ + int divertIn; + int divertOut; + int divertInOut; + int routeSock; + struct sockaddr_in addr; + fd_set readMask; + fd_set writeMask; + int fdMax; +/* + * Initialize packet aliasing software. + * Done already here to be able to alter option bits + * during command line and configuration file processing. + */ + PacketAliasInit (); +/* + * Parse options. + */ + inPort = 0; + outPort = 0; + verbose = 0; + inOutPort = 0; + ifName = NULL; + ifMTU = -1; + background = 0; + running = 1; + assignAliasAddr = 0; + aliasAddr.s_addr = INADDR_NONE; + aliasOverhead = 12; + dynamicMode = 0; + logDropped = 0; + logFacility = LOG_DAEMON; +/* + * Mark packet buffer empty. + */ + packetSock = -1; + packetDirection = DONT_KNOW; + + ParseArgs (argc, argv); +/* + * Open syslog channel. + */ + openlog ("natd", LOG_CONS | LOG_PID, logFacility); +/* + * Check that valid aliasing address has been given. + */ + if (aliasAddr.s_addr == INADDR_NONE && ifName == NULL) + errx (1, "aliasing address not given"); + + if (aliasAddr.s_addr != INADDR_NONE && ifName != NULL) + errx (1, "both alias address and interface " + "name are not allowed"); +/* + * Check that valid port number is known. + */ + if (inPort != 0 || outPort != 0) + if (inPort == 0 || outPort == 0) + errx (1, "both input and output ports are required"); + + if (inPort == 0 && outPort == 0 && inOutPort == 0) + ParseOption ("port", DEFAULT_SERVICE, 0); + +/* + * Check if ignored packets should be dropped. + */ + dropIgnoredIncoming = PacketAliasSetMode (0, 0); + dropIgnoredIncoming &= PKT_ALIAS_DENY_INCOMING; +/* + * Create divert sockets. Use only one socket if -p was specified + * on command line. Otherwise, create separate sockets for + * outgoing and incoming connnections. + */ + if (inOutPort) { + + divertInOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (divertInOut == -1) + Quit ("Unable to create divert socket."); + + divertIn = -1; + divertOut = -1; +/* + * Bind socket. + */ + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = inOutPort; + + if (bind (divertInOut, + (struct sockaddr*) &addr, + sizeof addr) == -1) + Quit ("Unable to bind divert socket."); + } + else { + + divertIn = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (divertIn == -1) + Quit ("Unable to create incoming divert socket."); + + divertOut = socket (PF_INET, SOCK_RAW, IPPROTO_DIVERT); + if (divertOut == -1) + Quit ("Unable to create outgoing divert socket."); + + divertInOut = -1; + +/* + * Bind divert sockets. + */ + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = inPort; + + if (bind (divertIn, + (struct sockaddr*) &addr, + sizeof addr) == -1) + Quit ("Unable to bind incoming divert socket."); + + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = outPort; + + if (bind (divertOut, + (struct sockaddr*) &addr, + sizeof addr) == -1) + Quit ("Unable to bind outgoing divert socket."); + } +/* + * Create routing socket if interface name specified. + */ + if (ifName && dynamicMode) { + + routeSock = socket (PF_ROUTE, SOCK_RAW, 0); + if (routeSock == -1) + Quit ("Unable to create routing info socket."); + } + else + routeSock = -1; +/* + * Create socket for sending ICMP messages. + */ + icmpSock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (icmpSock == -1) + Quit ("Unable to create ICMP socket."); + +/* + * And disable reads for the socket, otherwise it slowly fills + * up with received icmps which we do not use. + */ + shutdown(icmpSock, SHUT_RD); + +/* + * Become a daemon unless verbose mode was requested. + */ + if (!verbose) + DaemonMode (); +/* + * Catch signals to manage shutdown and + * refresh of interface address. + */ + signal (SIGTERM, InitiateShutdown); + signal (SIGHUP, RefreshAddr); +/* + * Set alias address if it has been given. + */ + if (aliasAddr.s_addr != INADDR_NONE) + PacketAliasSetAddress (aliasAddr); +/* + * We need largest descriptor number for select. + */ + + fdMax = -1; + + if (divertIn > fdMax) + fdMax = divertIn; + + if (divertOut > fdMax) + fdMax = divertOut; + + if (divertInOut > fdMax) + fdMax = divertInOut; + + if (routeSock > fdMax) + fdMax = routeSock; + + while (running) { + + if (divertInOut != -1 && !ifName && packetSock == -1) { +/* + * When using only one socket, just call + * DoAliasing repeatedly to process packets. + */ + DoAliasing (divertInOut, DONT_KNOW); + continue; + } +/* + * Build read mask from socket descriptors to select. + */ + FD_ZERO (&readMask); + FD_ZERO (&writeMask); + +/* + * If there is unsent packet in buffer, use select + * to check when socket comes writable again. + */ + if (packetSock != -1) { + + FD_SET (packetSock, &writeMask); + } + else { +/* + * No unsent packet exists - safe to check if + * new ones are available. + */ + if (divertIn != -1) + FD_SET (divertIn, &readMask); + + if (divertOut != -1) + FD_SET (divertOut, &readMask); + + if (divertInOut != -1) + FD_SET (divertInOut, &readMask); + } +/* + * Routing info is processed always. + */ + if (routeSock != -1) + FD_SET (routeSock, &readMask); + + if (select (fdMax + 1, + &readMask, + &writeMask, + NULL, + NULL) == -1) { + + if (errno == EINTR) + continue; + + Quit ("Select failed."); + } + + if (packetSock != -1) + if (FD_ISSET (packetSock, &writeMask)) + FlushPacketBuffer (packetSock); + + if (divertIn != -1) + if (FD_ISSET (divertIn, &readMask)) + DoAliasing (divertIn, INPUT); + + if (divertOut != -1) + if (FD_ISSET (divertOut, &readMask)) + DoAliasing (divertOut, OUTPUT); + + if (divertInOut != -1) + if (FD_ISSET (divertInOut, &readMask)) + DoAliasing (divertInOut, DONT_KNOW); + + if (routeSock != -1) + if (FD_ISSET (routeSock, &readMask)) + HandleRoutingInfo (routeSock); + } + + if (background) + unlink (PIDFILE); + + return 0; +} + +static void DaemonMode () +{ + FILE* pidFile; + + daemon (0, 0); + background = 1; + + pidFile = fopen (PIDFILE, "w"); + if (pidFile) { + + fprintf (pidFile, "%d\n", getpid ()); + fclose (pidFile); + } +} + +static void ParseArgs (int argc, char** argv) +{ + int arg; + char* parm; + char* opt; + char parmBuf[256]; + + for (arg = 1; arg < argc; arg++) { + + opt = argv[arg]; + if (*opt != '-') { + + warnx ("invalid option %s", opt); + Usage (); + } + + parm = NULL; + parmBuf[0] = '\0'; + + while (arg < argc - 1) { + + if (argv[arg + 1][0] == '-') + break; + + if (parm) + strcat (parmBuf, " "); + + ++arg; + parm = parmBuf; + strcat (parmBuf, argv[arg]); + } + + ParseOption (opt + 1, parm, 1); + } +} + +static void DoAliasing (int fd, int direction) +{ + int bytes; + int origBytes; + int status; + int addrSize; + struct ip* ip; + + if (assignAliasAddr) { + + SetAliasAddressFromIfName (ifName); + assignAliasAddr = 0; + } +/* + * Get packet from socket. + */ + addrSize = sizeof packetAddr; + origBytes = recvfrom (fd, + packetBuf, + sizeof packetBuf, + 0, + (struct sockaddr*) &packetAddr, + &addrSize); + + if (origBytes == -1) { + + if (errno != EINTR) + Warn ("read from divert socket failed"); + + return; + } +/* + * This is a IP packet. + */ + ip = (struct ip*) packetBuf; + if (direction == DONT_KNOW) + if (packetAddr.sin_addr.s_addr == INADDR_ANY) + direction = OUTPUT; + else + direction = INPUT; + + if (verbose) { + +/* + * Print packet direction and protocol type. + */ + printf (direction == OUTPUT ? "Out " : "In "); + + switch (ip->ip_p) { + case IPPROTO_TCP: + printf ("[TCP] "); + break; + + case IPPROTO_UDP: + printf ("[UDP] "); + break; + + case IPPROTO_ICMP: + printf ("[ICMP] "); + break; + + default: + printf ("[%d] ", ip->ip_p); + break; + } +/* + * Print addresses. + */ + PrintPacket (ip); + } + + if (direction == OUTPUT) { +/* + * Outgoing packets. Do aliasing. + */ + PacketAliasOut (packetBuf, IP_MAXPACKET); + } + else { + +/* + * Do aliasing. + */ + status = PacketAliasIn (packetBuf, IP_MAXPACKET); + if (status == PKT_ALIAS_IGNORED && + dropIgnoredIncoming) { + + if (verbose) + printf (" dropped.\n"); + + if (logDropped) + SyslogPacket (ip, LOG_WARNING, "denied"); + + return; + } + } +/* + * Length might have changed during aliasing. + */ + bytes = ntohs (ip->ip_len); +/* + * Update alias overhead size for outgoing packets. + */ + if (direction == OUTPUT && + bytes - origBytes > aliasOverhead) + aliasOverhead = bytes - origBytes; + + if (verbose) { + +/* + * Print addresses after aliasing. + */ + printf (" aliased to\n"); + printf (" "); + PrintPacket (ip); + printf ("\n"); + } + + packetLen = bytes; + packetSock = fd; + packetDirection = direction; + + FlushPacketBuffer (fd); +} + +static void FlushPacketBuffer (int fd) +{ + int wrote; + char msgBuf[80]; +/* + * Put packet back for processing. + */ + wrote = sendto (fd, + packetBuf, + packetLen, + 0, + (struct sockaddr*) &packetAddr, + sizeof packetAddr); + + if (wrote != packetLen) { +/* + * If buffer space is not available, + * just return. Main loop will take care of + * retrying send when space becomes available. + */ + if (errno == ENOBUFS) + return; + + if (errno == EMSGSIZE) { + + if (packetDirection == OUTPUT && + ifMTU != -1) + SendNeedFragIcmp (icmpSock, + (struct ip*) packetBuf, + ifMTU - aliasOverhead); + } + else { + + sprintf (msgBuf, "failed to write packet back"); + Warn (msgBuf); + } + } + + packetSock = -1; +} + +static void HandleRoutingInfo (int fd) +{ + int bytes; + struct if_msghdr ifMsg; +/* + * Get packet from socket. + */ + bytes = read (fd, &ifMsg, sizeof ifMsg); + if (bytes == -1) { + + Warn ("read from routing socket failed"); + return; + } + + if (ifMsg.ifm_version != RTM_VERSION) { + + Warn ("unexpected packet read from routing socket"); + return; + } + + if (verbose) + printf ("Routing message %X received.\n", ifMsg.ifm_type); + + if (ifMsg.ifm_type != RTM_NEWADDR) + return; + + if (verbose && ifMsg.ifm_index == ifIndex) + printf ("Interface address has changed.\n"); + + if (ifMsg.ifm_index == ifIndex) + assignAliasAddr = 1; +} + +static void PrintPacket (struct ip* ip) +{ + printf ("%s", FormatPacket (ip)); +} + +static void SyslogPacket (struct ip* ip, int priority, const char *label) +{ + syslog (priority, "%s %s", label, FormatPacket (ip)); +} + +static char* FormatPacket (struct ip* ip) +{ + static char buf[256]; + struct tcphdr* tcphdr; + struct udphdr* udphdr; + struct icmp* icmphdr; + char src[20]; + char dst[20]; + + strcpy (src, inet_ntoa (ip->ip_src)); + strcpy (dst, inet_ntoa (ip->ip_dst)); + + switch (ip->ip_p) { + case IPPROTO_TCP: + tcphdr = (struct tcphdr*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[TCP] %s:%d -> %s:%d", + src, + ntohs (tcphdr->th_sport), + dst, + ntohs (tcphdr->th_dport)); + break; + + case IPPROTO_UDP: + udphdr = (struct udphdr*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[UDP] %s:%d -> %s:%d", + src, + ntohs (udphdr->uh_sport), + dst, + ntohs (udphdr->uh_dport)); + break; + + case IPPROTO_ICMP: + icmphdr = (struct icmp*) ((char*) ip + (ip->ip_hl << 2)); + sprintf (buf, "[ICMP] %s -> %s %u(%u)", + src, + dst, + icmphdr->icmp_type, + icmphdr->icmp_code); + break; + + default: + sprintf (buf, "[%d] %s -> %s ", ip->ip_p, src, dst); + break; + } + + return buf; +} + +static void SetAliasAddressFromIfName (char* ifn) +{ + struct ifconf cf; + struct ifreq buf[32]; + char msg[80]; + struct ifreq* ifPtr; + int extra; + int helperSock; + int bytes; + struct sockaddr_in* addr; + int found; + struct ifreq req; + char last[10]; +/* + * Create a dummy socket to access interface information. + */ + helperSock = socket (AF_INET, SOCK_DGRAM, 0); + if (helperSock == -1) { + + Quit ("Failed to create helper socket."); + exit (1); + } + + cf.ifc_len = sizeof (buf); + cf.ifc_req = buf; +/* + * Get interface data. + */ + if (ioctl (helperSock, SIOCGIFCONF, &cf) == -1) { + + Quit ("Ioctl SIOCGIFCONF failed."); + exit (1); + } + + ifIndex = 0; + ifPtr = buf; + bytes = cf.ifc_len; + found = 0; + last[0] = '\0'; +/* + * Loop through interfaces until one with + * given name is found. This is done to + * find correct interface index for routing + * message processing. + */ + while (bytes) { + + if (ifPtr->ifr_addr.sa_family == AF_INET && + !strcmp (ifPtr->ifr_name, ifn)) { + + found = 1; + break; + } + + if (strcmp (last, ifPtr->ifr_name)) { + + strcpy (last, ifPtr->ifr_name); + ++ifIndex; + } + + extra = ifPtr->ifr_addr.sa_len - sizeof (struct sockaddr); + + ifPtr++; + ifPtr = (struct ifreq*) ((char*) ifPtr + extra); + bytes -= sizeof (struct ifreq) + extra; + } + + if (!found) { + + close (helperSock); + sprintf (msg, "Unknown interface name %s.\n", ifn); + Quit (msg); + } +/* + * Get MTU size. + */ + strcpy (req.ifr_name, ifn); + + if (ioctl (helperSock, SIOCGIFMTU, &req) == -1) + Quit ("Cannot get interface mtu size."); + + ifMTU = req.ifr_mtu; +/* + * Get interface address. + */ + if (ioctl (helperSock, SIOCGIFADDR, &req) == -1) + Quit ("Cannot get interface address."); + + addr = (struct sockaddr_in*) &req.ifr_addr; + PacketAliasSetAddress (addr->sin_addr); + syslog (LOG_INFO, "Aliasing to %s, mtu %d bytes", + inet_ntoa (addr->sin_addr), + ifMTU); + + close (helperSock); +} + +void Quit (const char* msg) +{ + Warn (msg); + exit (1); +} + +void Warn (const char* msg) +{ + if (background) + syslog (LOG_ALERT, "%s (%m)", msg); + else + warn (msg); +} + +static void RefreshAddr (int sig) +{ + signal (SIGHUP, RefreshAddr); + if (ifName) + assignAliasAddr = 1; +} + +static void InitiateShutdown (int sig) +{ +/* + * Start timer to allow kernel gracefully + * shutdown existing connections when system + * is shut down. + */ + signal (SIGALRM, Shutdown); + alarm (10); +} + +static void Shutdown (int sig) +{ + running = 0; +} + +/* + * Different options recognized by this program. + */ + +enum Option { + + PacketAliasOption, + Verbose, + InPort, + OutPort, + Port, + AliasAddress, + InterfaceName, + RedirectPort, + RedirectAddress, + ConfigFile, + DynamicMode, + PptpAlias, + ProxyRule, + LogDenied, + LogFacility +}; + +enum Param { + + YesNo, + Numeric, + String, + None, + Address, + Service +}; + +/* + * Option information structure (used by ParseOption). + */ + +struct OptionInfo { + + enum Option type; + int packetAliasOpt; + enum Param parm; + const char* parmDescription; + const char* description; + const char* name; + const char* shortName; +}; + +/* + * Table of known options. + */ + +static struct OptionInfo optionTable[] = { + + { PacketAliasOption, + PKT_ALIAS_UNREGISTERED_ONLY, + YesNo, + "[yes|no]", + "alias only unregistered addresses", + "unregistered_only", + "u" }, + + { PacketAliasOption, + PKT_ALIAS_LOG, + YesNo, + "[yes|no]", + "enable logging", + "log", + "l" }, + + { PacketAliasOption, + PKT_ALIAS_PROXY_ONLY, + YesNo, + "[yes|no]", + "proxy only", + "proxy_only", + NULL }, + + { PacketAliasOption, + PKT_ALIAS_REVERSE, + YesNo, + "[yes|no]", + "operate in reverse mode", + "reverse", + NULL }, + + { PacketAliasOption, + PKT_ALIAS_DENY_INCOMING, + YesNo, + "[yes|no]", + "allow incoming connections", + "deny_incoming", + "d" }, + + { PacketAliasOption, + PKT_ALIAS_USE_SOCKETS, + YesNo, + "[yes|no]", + "use sockets to inhibit port conflict", + "use_sockets", + "s" }, + + { PacketAliasOption, + PKT_ALIAS_SAME_PORTS, + YesNo, + "[yes|no]", + "try to keep original port numbers for connections", + "same_ports", + "m" }, + + { Verbose, + 0, + YesNo, + "[yes|no]", + "verbose mode, dump packet information", + "verbose", + "v" }, + + { DynamicMode, + 0, + YesNo, + "[yes|no]", + "dynamic mode, automatically detect interface address changes", + "dynamic", + NULL }, + + { InPort, + 0, + Service, + "number|service_name", + "set port for incoming packets", + "in_port", + "i" }, + + { OutPort, + 0, + Service, + "number|service_name", + "set port for outgoing packets", + "out_port", + "o" }, + + { Port, + 0, + Service, + "number|service_name", + "set port (defaults to natd/divert)", + "port", + "p" }, + + { AliasAddress, + 0, + Address, + "x.x.x.x", + "address to use for aliasing", + "alias_address", + "a" }, + + { InterfaceName, + 0, + String, + "network_if_name", + "take aliasing address from interface", + "interface", + "n" }, + + { ProxyRule, + 0, + String, + "[type encode_ip_hdr|encode_tcp_stream] port xxxx server " + "a.b.c.d:yyyy", + "add transparent proxying / destination NAT", + "proxy_rule", + NULL }, + + { RedirectPort, + 0, + String, + "tcp|udp local_addr:local_port_range [public_addr:]public_port_range" + " [remote_addr[:remote_port_range]]", + "redirect a port (or ports) for incoming traffic", + "redirect_port", + NULL }, + + { RedirectAddress, + 0, + String, + "local_addr public_addr", + "define mapping between local and public addresses", + "redirect_address", + NULL }, + + { PptpAlias, + 0, + String, + "src", + "define inside machine for PPTP traffic", + "pptpalias", + NULL }, + + { ConfigFile, + 0, + String, + "file_name", + "read options from configuration file", + "config", + "f" }, + + { LogDenied, + 0, + YesNo, + "[yes|no]", + "enable logging of denied incoming packets", + "log_denied", + NULL }, + + { LogFacility, + 0, + String, + "facility", + "name of syslog facility to use for logging", + "log_facility", + NULL } + +}; + +static void ParseOption (const char* option, const char* parms, int cmdLine) +{ + int i; + struct OptionInfo* info; + int yesNoValue; + int aliasValue; + int numValue; + u_short uNumValue; + const char* strValue; + struct in_addr addrValue; + int max; + char* end; + CODE* fac_record = NULL; +/* + * Find option from table. + */ + max = sizeof (optionTable) / sizeof (struct OptionInfo); + for (i = 0, info = optionTable; i < max; i++, info++) { + + if (!strcmp (info->name, option)) + break; + + if (info->shortName) + if (!strcmp (info->shortName, option)) + break; + } + + if (i >= max) { + + warnx ("unknown option %s", option); + Usage (); + } + + uNumValue = 0; + yesNoValue = 0; + numValue = 0; + strValue = NULL; +/* + * Check parameters. + */ + switch (info->parm) { + case YesNo: + if (!parms) + parms = "yes"; + + if (!strcmp (parms, "yes")) + yesNoValue = 1; + else + if (!strcmp (parms, "no")) + yesNoValue = 0; + else + errx (1, "%s needs yes/no parameter", option); + break; + + case Service: + if (!parms) + errx (1, "%s needs service name or " + "port number parameter", + option); + + uNumValue = StrToPort (parms, "divert"); + break; + + case Numeric: + if (parms) + numValue = strtol (parms, &end, 10); + else + end = NULL; + + if (end == parms) + errx (1, "%s needs numeric parameter", option); + break; + + case String: + strValue = parms; + if (!strValue) + errx (1, "%s needs parameter", option); + break; + + case None: + if (parms) + errx (1, "%s does not take parameters", option); + break; + + case Address: + if (!parms) + errx (1, "%s needs address/host parameter", option); + + StrToAddr (parms, &addrValue); + break; + } + + switch (info->type) { + case PacketAliasOption: + + aliasValue = yesNoValue ? info->packetAliasOpt : 0; + PacketAliasSetMode (aliasValue, info->packetAliasOpt); + break; + + case Verbose: + verbose = yesNoValue; + break; + + case DynamicMode: + dynamicMode = yesNoValue; + break; + + case InPort: + inPort = uNumValue; + break; + + case OutPort: + outPort = uNumValue; + break; + + case Port: + inOutPort = uNumValue; + break; + + case AliasAddress: + memcpy (&aliasAddr, &addrValue, sizeof (struct in_addr)); + break; + + case RedirectPort: + SetupPortRedirect (strValue); + break; + + case RedirectAddress: + SetupAddressRedirect (strValue); + break; + + case PptpAlias: + SetupPptpAlias (strValue); + break; + + case ProxyRule: + PacketAliasProxyRule (strValue); + break; + + case InterfaceName: + if (ifName) + free (ifName); + + ifName = strdup (strValue); + assignAliasAddr = 1; + break; + + case ConfigFile: + ReadConfigFile (strValue); + break; + + case LogDenied: + logDropped = 1; + break; + + case LogFacility: + + fac_record = facilitynames; + while (fac_record->c_name != NULL) { + + if (!strcmp (fac_record->c_name, strValue)) { + + logFacility = fac_record->c_val; + break; + + } + else + fac_record++; + } + + if(fac_record->c_name == NULL) + errx(1, "Unknown log facility name: %s", strValue); + + break; + } +} + +void ReadConfigFile (const char* fileName) +{ + FILE* file; + char buf[128]; + char* ptr; + char* option; + + file = fopen (fileName, "r"); + if (!file) { + + sprintf (buf, "Cannot open config file %s.\n", fileName); + Quit (buf); + } + + while (fgets (buf, sizeof (buf), file)) { + + ptr = strchr (buf, '\n'); + if (!ptr) + errx (1, "config line too long: %s", buf); + + *ptr = '\0'; + if (buf[0] == '#') + continue; + + ptr = buf; +/* + * Skip white space at beginning of line. + */ + while (*ptr && isspace (*ptr)) + ++ptr; + + if (*ptr == '\0') + continue; +/* + * Extract option name. + */ + option = ptr; + while (*ptr && !isspace (*ptr)) + ++ptr; + + if (*ptr != '\0') { + + *ptr = '\0'; + ++ptr; + } +/* + * Skip white space between name and parms. + */ + while (*ptr && isspace (*ptr)) + ++ptr; + + ParseOption (option, *ptr ? ptr : NULL, 0); + } + + fclose (file); +} + +static void Usage () +{ + int i; + int max; + struct OptionInfo* info; + + fprintf (stderr, "Recognized options:\n\n"); + + max = sizeof (optionTable) / sizeof (struct OptionInfo); + for (i = 0, info = optionTable; i < max; i++, info++) { + + fprintf (stderr, "-%-20s %s\n", info->name, + info->parmDescription); + + if (info->shortName) + fprintf (stderr, "-%-20s %s\n", info->shortName, + info->parmDescription); + + fprintf (stderr, " %s\n\n", info->description); + } + + exit (1); +} + +void SetupPptpAlias (const char* parms) +{ + char buf[128]; + char* ptr; + struct in_addr srcAddr; + + strcpy (buf, parms); + +/* + * Extract source address. + */ + ptr = strtok (buf, " \t"); + if (!ptr) + errx(1, "pptpalias: missing src address"); + + StrToAddr (ptr, &srcAddr); + PacketAliasPptp (srcAddr); +} + +void SetupPortRedirect (const char* parms) +{ + char buf[128]; + char* ptr; + struct in_addr localAddr; + struct in_addr publicAddr; + struct in_addr remoteAddr; + port_range portRange; + u_short localPort = 0; + u_short publicPort = 0; + u_short remotePort = 0; + u_short numLocalPorts = 0; + u_short numPublicPorts = 0; + u_short numRemotePorts = 0; + int proto; + char* protoName; + char* separator; + int i; + + strcpy (buf, parms); +/* + * Extract protocol. + */ + protoName = strtok (buf, " \t"); + if (!protoName) + errx (1, "redirect_port: missing protocol"); + + proto = StrToProto (protoName); +/* + * Extract local address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) + errx (1, "redirect_port: missing local address"); + + if ( StrToAddrAndPortRange (ptr, &localAddr, protoName, &portRange) != 0 ) + errx (1, "redirect_port: invalid local port range"); + + localPort = GETLOPORT(portRange); + numLocalPorts = GETNUMPORTS(portRange); + +/* + * Extract public port and optinally address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) + errx (1, "redirect_port: missing public port"); + + separator = strchr (ptr, ':'); + if (separator) { + if (StrToAddrAndPortRange (ptr, &publicAddr, protoName, &portRange) != 0 ) + errx (1, "redirect_port: invalid public port range"); + } + else { + publicAddr.s_addr = INADDR_ANY; + if (StrToPortRange (ptr, protoName, &portRange) != 0) + errx (1, "redirect_port: invalid public port range"); + } + + publicPort = GETLOPORT(portRange); + numPublicPorts = GETNUMPORTS(portRange); + +/* + * Extract remote address and optionally port. + */ + ptr = strtok (NULL, " \t"); + if (ptr) { + separator = strchr (ptr, ':'); + if (separator) + if (StrToAddrAndPortRange (ptr, &remoteAddr, protoName, &portRange) != 0) + errx (1, "redirect_port: invalid remote port range"); + else { + SETLOPORT(portRange, 0); + SETNUMPORTS(portRange, 1); + StrToAddr (ptr, &remoteAddr); + } + } + else { + SETLOPORT(portRange, 0); + SETNUMPORTS(portRange, 1); + remoteAddr.s_addr = INADDR_ANY; + } + + remotePort = GETLOPORT(portRange); + numRemotePorts = GETNUMPORTS(portRange); + +/* + * Make sure port ranges match up, then add the redirect ports. + */ + if (numLocalPorts != numPublicPorts) + errx (1, "redirect_port: port ranges must be equal in size"); + + /* Remote port range is allowed to be '0' which means all ports. */ + if (numRemotePorts != numLocalPorts && numRemotePorts != 1 && remotePort != 0) + errx (1, "redirect_port: remote port must be 0 or equal to local port range in size"); + + for (i = 0 ; i < numPublicPorts ; ++i) { + /* If remotePort is all ports, set it to 0. */ + u_short remotePortCopy = remotePort + i; + if (numRemotePorts == 1 && remotePort == 0) + remotePortCopy = 0; + + PacketAliasRedirectPort (localAddr, + htons(localPort + i), + remoteAddr, + htons(remotePortCopy), + publicAddr, + htons(publicPort + i), + proto); + } +} + +void SetupAddressRedirect (const char* parms) +{ + char buf[128]; + char* ptr; + struct in_addr localAddr; + struct in_addr publicAddr; + + strcpy (buf, parms); +/* + * Extract local address. + */ + ptr = strtok (buf, " \t"); + if (!ptr) + errx (1, "redirect_address: missing local address"); + + StrToAddr (ptr, &localAddr); +/* + * Extract public address. + */ + ptr = strtok (NULL, " \t"); + if (!ptr) + errx (1, "redirect_address: missing public address"); + + StrToAddr (ptr, &publicAddr); + PacketAliasRedirectAddr (localAddr, publicAddr); +} + +void StrToAddr (const char* str, struct in_addr* addr) +{ + struct hostent* hp; + + if (inet_aton (str, addr)) + return; + + hp = gethostbyname (str); + if (!hp) + errx (1, "unknown host %s", str); + + memcpy (addr, hp->h_addr, sizeof (struct in_addr)); +} + +u_short StrToPort (const char* str, const char* proto) +{ + u_short port; + struct servent* sp; + char* end; + + port = strtol (str, &end, 10); + if (end != str) + return htons (port); + + sp = getservbyname (str, proto); + if (!sp) + errx (1, "unknown service %s/%s", str, proto); + + return sp->s_port; +} + +int StrToPortRange (const char* str, const char* proto, port_range *portRange) +{ + char* sep; + struct servent* sp; + char* end; + u_short loPort; + u_short hiPort; + + /* First see if this is a service, return corresponding port if so. */ + sp = getservbyname (str,proto); + if (sp) { + SETLOPORT(*portRange, ntohs(sp->s_port)); + SETNUMPORTS(*portRange, 1); + return 0; + } + + /* Not a service, see if it's a single port or port range. */ + sep = strchr (str, '-'); + if (sep == NULL) { + SETLOPORT(*portRange, strtol(str, &end, 10)); + if (end != str) { + /* Single port. */ + SETNUMPORTS(*portRange, 1); + return 0; + } + + /* Error in port range field. */ + errx (1, "unknown service %s/%s", str, proto); + } + + /* Port range, get the values and sanity check. */ + sscanf (str, "%hu-%hu", &loPort, &hiPort); + SETLOPORT(*portRange, loPort); + SETNUMPORTS(*portRange, 0); /* Error by default */ + if (loPort <= hiPort) + SETNUMPORTS(*portRange, hiPort - loPort + 1); + + if (GETNUMPORTS(*portRange) == 0) + errx (1, "invalid port range %s", str); + + return 0; +} + + +int StrToProto (const char* str) +{ + if (!strcmp (str, "tcp")) + return IPPROTO_TCP; + + if (!strcmp (str, "udp")) + return IPPROTO_UDP; + + errx (1, "unknown protocol %s. Expected tcp or udp", str); +} + +int StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange) +{ + char* ptr; + + ptr = strchr (str, ':'); + if (!ptr) + errx (1, "%s is missing port number", str); + + *ptr = '\0'; + ++ptr; + + StrToAddr (str, addr); + return StrToPortRange (ptr, proto, portRange); +} diff --git a/natd.tproj/natd.h b/natd.tproj/natd.h new file mode 100644 index 0000000..f179cb5 --- /dev/null +++ b/natd.tproj/natd.h @@ -0,0 +1,24 @@ +/* + * natd - Network Address Translation Daemon for FreeBSD. + * + * This software is provided free of charge, with no + * warranty of any kind, either expressed or implied. + * Use at your own risk. + * + * You may copy, modify and distribute this software (natd.h) freely. + * + * Ari Suutari + * + * $Id: natd.h,v 1.1.1.1 2000/01/11 01:48:51 wsanchez Exp $ + */ + +#define PIDFILE "/var/run/natd.pid" +#define INPUT 1 +#define OUTPUT 2 +#define DONT_KNOW 3 + +extern void Quit (const char* msg); +extern void Warn (const char* msg); +extern int SendNeedFragIcmp (int sock, struct ip* failedDgram, int mtu); + + diff --git a/netstat.tproj/DERIVED_FILES b/netstat.tproj/DERIVED_FILES new file mode 100644 index 0000000..a4fa6c9 --- /dev/null +++ b/netstat.tproj/DERIVED_FILES @@ -0,0 +1 @@ +unix/bsd/netiso/tp_astring.c diff --git a/netstat.tproj/Makefile b/netstat.tproj/Makefile new file mode 100644 index 0000000..a009e36 --- /dev/null +++ b/netstat.tproj/Makefile @@ -0,0 +1,54 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = netstat + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = netstat.h + +CFILES = data.c if.c inet.c iso.c main.c mbuf.c mroute.c route.c\ + tp_astring.c unix.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble netstat.1\ + DERIVED_FILES + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +HEADER_PATHS =\ + -I$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd/netat + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/netstat.tproj/Makefile.postamble b/netstat.tproj/Makefile.postamble new file mode 100644 index 0000000..34d448d --- /dev/null +++ b/netstat.tproj/Makefile.postamble @@ -0,0 +1,2 @@ +INSTALL_AS_USER = root +INSTALL_PERMISSIONS =4555 diff --git a/netstat.tproj/Makefile.preamble b/netstat.tproj/Makefile.preamble new file mode 100644 index 0000000..cc0d3d0 --- /dev/null +++ b/netstat.tproj/Makefile.preamble @@ -0,0 +1,4 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include +vpath %.c `pwd` diff --git a/netstat.tproj/PB.project b/netstat.tproj/PB.project new file mode 100644 index 0000000..91d9ed6 --- /dev/null +++ b/netstat.tproj/PB.project @@ -0,0 +1,49 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + HEADERSEARCH = ( + "$(NEXT_ROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks/System.framework/PrivateHeaders/bsd/netat" + ); + H_FILES = (netstat.h); + LIBRARYSEARCH = (); + OTHER_LIBS = (); + OTHER_LINKED = ( + data.c, + if.c, + inet.c, + iso.c, + main.c, + mbuf.c, + mroute.c, + route.c, + tp_astring.c, + unix.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, netstat.1, DERIVED_FILES); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = netstat; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/netstat.tproj/data.c b/netstat.tproj/data.c new file mode 100644 index 0000000..9e0bbe2 --- /dev/null +++ b/netstat.tproj/data.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* NeXT */ +#ifndef EXTERN +#define EXTERN +#endif +#include "netstat.h" diff --git a/netstat.tproj/if.c b/netstat.tproj/if.c new file mode 100644 index 0000000..43be850 --- /dev/null +++ b/netstat.tproj/if.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +/* +static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95"; +*/ +static const char rcsid[] = + "$Id: if.c,v 1.1.1.2 2000/01/11 01:48:51 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef IPX +#include +#include +#endif + +#ifdef NS +#include +#include +#endif +#ifdef ISO +#include +#include +#endif +#include + +#include +#include +#include +#include + +#include "netstat.h" + +#define YES 1 +#define NO 0 + +static void sidewaysintpr __P((u_int, u_long)); +static void catchalarm __P((int)); + +/* + * Print a description of the network interfaces. + */ +void +intpr(interval, ifnetaddr) + int interval; + u_long ifnetaddr; +{ + struct ifnet ifnet; + struct ifnethead ifnethead; + union { + struct ifaddr ifa; + struct in_ifaddr in; +#ifdef IPX + struct ipx_ifaddr ipx; +#endif +#ifdef NS + struct ns_ifaddr ns; +#endif +#ifdef ISO + struct iso_ifaddr iso; +#endif + } ifaddr; + u_long ifaddraddr; + u_long ifaddrfound; + u_long ifnetfound; + struct sockaddr *sa; + char name[32], tname[16]; + + if (ifnetaddr == 0) { + printf("ifnet: symbol not defined\n"); + return; + } + if (interval) { + sidewaysintpr((unsigned)interval, ifnetaddr); + return; + } + if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead)) + return; + ifnetaddr = (u_long)ifnethead.tqh_first; + if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet)) + return; + + printf("%-5.5s %-5.5s %-13.13s %-15.15s %8.8s %5.5s", + "Name", "Mtu", "Network", "Address", "Ipkts", "Ierrs"); + if (bflag) + printf(" %10.10s","Ibytes"); + printf(" %8.8s %5.5s", "Opkts", "Oerrs"); + if (bflag) + printf(" %10.10s","Obytes"); + printf(" %5s", "Coll"); + if (tflag) + printf(" %s", "Time"); + if (dflag) + printf(" %s", "Drop"); + putchar('\n'); + ifaddraddr = 0; + while (ifnetaddr || ifaddraddr) { + struct sockaddr_in *sin; + register char *cp; + int n, m; + + if (ifaddraddr == 0) { + ifnetfound = ifnetaddr; + if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) || + kread((u_long)ifnet.if_name, tname, 16)) + return; + tname[15] = '\0'; + ifnetaddr = (u_long)ifnet.if_link.tqe_next; + snprintf(name, 32, "%s%d", tname, ifnet.if_unit); + if (interface != 0 && (strcmp(name, interface) != 0)) + continue; + cp = index(name, '\0'); + if ((ifnet.if_flags&IFF_UP) == 0) + *cp++ = '*'; + *cp = '\0'; + ifaddraddr = (u_long)ifnet.if_addrhead.tqh_first; + } + printf("%-5.5s %-5lu ", name, ifnet.if_mtu); + ifaddrfound = ifaddraddr; + if (ifaddraddr == 0) { + printf("%-13.13s ", "none"); + printf("%-15.15s ", "none"); + } else { + if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)) { + ifaddraddr = 0; + continue; + } +#define CP(x) ((char *)(x)) + cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) + + CP(&ifaddr); sa = (struct sockaddr *)cp; + switch (sa->sa_family) { + case AF_UNSPEC: + printf("%-13.13s ", "none"); + printf("%-15.15s ", "none"); + break; + case AF_INET: + sin = (struct sockaddr_in *)sa; +#ifdef notdef + /* can't use inet_makeaddr because kernel + * keeps nets unshifted. + */ + in = inet_makeaddr(ifaddr.in.ia_subnet, + INADDR_ANY); + printf("%-13.13s ", netname(in.s_addr, + ifaddr.in.ia_subnetmask)); +#else + printf("%-13.13s ", + netname(htonl(ifaddr.in.ia_subnet), + ifaddr.in.ia_subnetmask)); +#endif + printf("%-15.15s ", + routename(sin->sin_addr.s_addr)); + break; +#ifdef IPX + + case AF_IPX: + { + struct sockaddr_ipx *sipx = + (struct sockaddr_ipx *)sa; + u_long net; + char netnum[10]; + + *(union ipx_net *) &net = sipx->sipx_addr.x_net; + sprintf(netnum, "%lx", (u_long)ntohl(net)); + printf("ipx:%-8s ", netnum); +/* printf("ipx:%-8s ", netname(net, 0L)); */ + printf("%-15s ", + ipx_phost((struct sockaddr *)sipx)); + } + break; +#endif +#if 0 + case AF_APPLETALK: + printf("atalk:%-12.12s ",atalk_print(sa,0x10) ); + printf("%-9.9s ",atalk_print(sa,0x0b) ); + break; +#endif +#ifdef NS + case AF_NS: + { + struct sockaddr_ns *sns = + (struct sockaddr_ns *)sa; + u_long net; + char netnum[10]; + + *(union ns_net *) &net = sns->sns_addr.x_net; + sprintf(netnum, "%lxH", ntohl(net)); + upHex(netnum); + printf("ns:%-8s ", netnum); + printf("%-15s ", + ns_phost((struct sockaddr *)sns)); + } + break; +#endif + case AF_LINK: + { + struct sockaddr_dl *sdl = + (struct sockaddr_dl *)sa; + cp = (char *)LLADDR(sdl); + n = sdl->sdl_alen; + } + m = printf("%-11.11s ", ""); + goto hexprint; + default: + m = printf("(%d)", sa->sa_family); + for (cp = sa->sa_len + (char *)sa; + --cp > sa->sa_data && (*cp == 0);) {} + n = cp - sa->sa_data + 1; + cp = sa->sa_data; + hexprint: + while (--n >= 0) + m += printf("%02x%c", *cp++ & 0xff, + n > 0 ? '.' : ' '); + m = 30 - m; + while (m-- > 0) + putchar(' '); + break; + } + ifaddraddr = (u_long)ifaddr.ifa.ifa_link.tqe_next; + } + printf("%8lu %5lu ", + ifnet.if_ipackets, ifnet.if_ierrors); + if (bflag) + printf("%10lu ", ifnet.if_ibytes); + printf("%8lu %5lu ", + ifnet.if_opackets, ifnet.if_oerrors); + if (bflag) + printf("%10lu ", ifnet.if_obytes); + printf("%5lu", ifnet.if_collisions); + if (tflag) + printf(" %3d", ifnet.if_timer); + if (dflag) + printf(" %3d", ifnet.if_snd.ifq_drops); + putchar('\n'); + if (aflag && ifaddrfound) { + /* + * Print family's multicast addresses + */ + u_long multiaddr; + struct ifmultiaddr ifma; + union { + struct sockaddr sa; + struct sockaddr_in in; + struct sockaddr_dl dl; + } msa; + const char *fmt; + + for(multiaddr = (u_long)ifnet.if_multiaddrs.lh_first; + multiaddr; + multiaddr = (u_long)ifma.ifma_link.le_next) { + if (kread(multiaddr, (char *)&ifma, + sizeof ifma)) + break; + if (kread((u_long)ifma.ifma_addr, (char *)&msa, + sizeof msa)) + break; + if (msa.sa.sa_family != sa->sa_family) + continue; + + fmt = 0; + switch (msa.sa.sa_family) { + case AF_INET: + fmt = routename(msa.in.sin_addr.s_addr); + break; + + case AF_LINK: + switch (ifnet.if_type) { + case IFT_ETHER: + case IFT_FDDI: + fmt = ether_ntoa( + (struct ether_addr *) + LLADDR(&msa.dl)); + break; + } + break; + } + if (fmt) + printf("%23s %s\n", "", fmt); + } + } + } +} + +#define MAXIF 10 +struct iftot { + char ift_name[16]; /* interface name */ + u_int ift_ip; /* input packets */ + u_int ift_ie; /* input errors */ + u_int ift_op; /* output packets */ + u_int ift_oe; /* output errors */ + u_int ift_co; /* collisions */ + u_int ift_dr; /* drops */ + u_int ift_ib; /* input bytes */ + u_int ift_ob; /* output bytes */ +} iftot[MAXIF]; + +u_char signalled; /* set if alarm goes off "early" */ + +/* + * Print a running summary of interface statistics. + * Repeat display every interval seconds, showing statistics + * collected over that interval. Assumes that interval is non-zero. + * First line printed at top of screen is always cumulative. + * XXX - should be rewritten to use ifmib(4). + */ +static void +sidewaysintpr(interval, off) + unsigned interval; + u_long off; +{ + struct ifnet ifnet; + u_long firstifnet; + struct ifnethead ifnethead; + register struct iftot *ip, *total; + register int line; + struct iftot *lastif, *sum, *interesting; + int oldmask, first; + u_long interesting_off; + + if (kread(off, (char *)&ifnethead, sizeof ifnethead)) + return; + firstifnet = (u_long)ifnethead.tqh_first; + + lastif = iftot; + sum = iftot + MAXIF - 1; + total = sum - 1; + interesting = NULL; + interesting_off = 0; + for (off = firstifnet, ip = iftot; off;) { + char name[16], tname[16]; + + if (kread(off, (char *)&ifnet, sizeof ifnet)) + break; + if (kread((u_long)ifnet.if_name, tname, 16)) + break; + tname[15] = '\0'; + snprintf(name, 16, "%s%d", tname, ifnet.if_unit); + if (interface && strcmp(name, interface) == 0) { + interesting = ip; + interesting_off = off; + } + snprintf(ip->ift_name, 16, "(%s)", name);; + ip++; + if (ip >= iftot + MAXIF - 2) + break; + off = (u_long) ifnet.if_link.tqe_next; + } + lastif = ip; + + (void)signal(SIGALRM, catchalarm); + signalled = NO; + (void)alarm(interval); + for (ip = iftot; ip < iftot + MAXIF; ip++) { + ip->ift_ip = 0; + ip->ift_ie = 0; + ip->ift_ib = 0; + ip->ift_op = 0; + ip->ift_oe = 0; + ip->ift_ob = 0; + ip->ift_co = 0; + ip->ift_dr = 0; + } + first = 1; +banner: + printf("%17s %14s %16s", "input", + interesting ? interesting->ift_name : "(Total)", "output"); + putchar('\n'); + printf("%10s %5s %10s %10s %5s %10s %5s", + "packets", "errs", "bytes", "packets", "errs", "bytes", "colls"); + if (dflag) + printf(" %5.5s", "drops"); + putchar('\n'); + fflush(stdout); + line = 0; +loop: + if (interesting != NULL) { + ip = interesting; + if (kread(interesting_off, (char *)&ifnet, sizeof ifnet)) { + printf("???\n"); + exit(1); + }; + if (!first) { + printf("%10lu %5lu %10lu %10lu %5lu %10lu %5lu", + ifnet.if_ipackets - ip->ift_ip, + ifnet.if_ierrors - ip->ift_ie, + ifnet.if_ibytes - ip->ift_ib, + ifnet.if_opackets - ip->ift_op, + ifnet.if_oerrors - ip->ift_oe, + ifnet.if_obytes - ip->ift_ob, + ifnet.if_collisions - ip->ift_co); + if (dflag) + printf(" %5u", ifnet.if_snd.ifq_drops - ip->ift_dr); + } + ip->ift_ip = ifnet.if_ipackets; + ip->ift_ie = ifnet.if_ierrors; + ip->ift_ib = ifnet.if_ibytes; + ip->ift_op = ifnet.if_opackets; + ip->ift_oe = ifnet.if_oerrors; + ip->ift_ob = ifnet.if_obytes; + ip->ift_co = ifnet.if_collisions; + ip->ift_dr = ifnet.if_snd.ifq_drops; + } else { + sum->ift_ip = 0; + sum->ift_ie = 0; + sum->ift_ib = 0; + sum->ift_op = 0; + sum->ift_oe = 0; + sum->ift_ob = 0; + sum->ift_co = 0; + sum->ift_dr = 0; + for (off = firstifnet, ip = iftot; off && ip < lastif; ip++) { + if (kread(off, (char *)&ifnet, sizeof ifnet)) { + off = 0; + continue; + } + sum->ift_ip += ifnet.if_ipackets; + sum->ift_ie += ifnet.if_ierrors; + sum->ift_ib += ifnet.if_ibytes; + sum->ift_op += ifnet.if_opackets; + sum->ift_oe += ifnet.if_oerrors; + sum->ift_ob += ifnet.if_obytes; + sum->ift_co += ifnet.if_collisions; + sum->ift_dr += ifnet.if_snd.ifq_drops; + off = (u_long) ifnet.if_link.tqe_next; + } + if (!first) { + printf("%10u %5u %10u %10u %5u %10u %5u", + sum->ift_ip - total->ift_ip, + sum->ift_ie - total->ift_ie, + sum->ift_ib - total->ift_ib, + sum->ift_op - total->ift_op, + sum->ift_oe - total->ift_oe, + sum->ift_ob - total->ift_ob, + sum->ift_co - total->ift_co); + if (dflag) + printf(" %5u", sum->ift_dr - total->ift_dr); + } + *total = *sum; + } + if (!first) + putchar('\n'); + fflush(stdout); + oldmask = sigblock(sigmask(SIGALRM)); + if (! signalled) { + sigpause(0); + } + sigsetmask(oldmask); + signalled = NO; + (void)alarm(interval); + line++; + first = 0; + if (line == 21) + goto banner; + else + goto loop; + /*NOTREACHED*/ +} + +/* + * Called if an interval expires before sidewaysintpr has completed a loop. + * Sets a flag to not wait for the alarm. + */ +static void +catchalarm(signo) + int signo; +{ + signalled = YES; +} diff --git a/netstat.tproj/inet.c b/netstat.tproj/inet.c new file mode 100644 index 0000000..0c2250a --- /dev/null +++ b/netstat.tproj/inet.c @@ -0,0 +1,616 @@ +/* + * Copyright (c) 1983, 1988, 1993, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +/* +static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; +*/ +static const char rcsid[] = + "$Id: inet.c,v 1.1.1.2 2000/01/11 01:48:52 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define TCPSTATES +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "netstat.h" + +char *inetname __P((struct in_addr *)); +void inetprint __P((struct in_addr *, int, char *, int)); + +/* + * Print a summary of connections related to an Internet + * protocol. For TCP, also give state of connection. + * Listening processes (aflag) are suppressed unless the + * -a (all) flag is specified. + */ +void +protopr(proto, name) + u_long proto; /* for sysctl version we pass proto # */ + char *name; +{ + int istcp; + static int first = 1; + char *buf; + const char *mibvar; + struct tcpcb *tp; + struct inpcb *inp; + struct xinpgen *xig, *oxig; + struct xsocket *so; + size_t len; + + istcp = 0; + switch (proto) { + case IPPROTO_TCP: + istcp = 1; + mibvar = "net.inet.tcp.pcblist"; + break; + case IPPROTO_UDP: + mibvar = "net.inet.udp.pcblist"; + break; + case IPPROTO_DIVERT: + mibvar = "net.inet.divert.pcblist"; + break; + default: + mibvar = "net.inet.raw.pcblist"; + break; + } + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + return; + } + if ((buf = malloc(len)) == 0) { + warn("malloc %lu bytes", (u_long)len); + return; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + free(buf); + return; + } + + oxig = xig = (struct xinpgen *)buf; + for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); + xig->xig_len > sizeof(struct xinpgen); + xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { + if (istcp) { + tp = &((struct xtcpcb *)xig)->xt_tp; + inp = &((struct xtcpcb *)xig)->xt_inp; + so = &((struct xtcpcb *)xig)->xt_socket; + } else { + inp = &((struct xinpcb *)xig)->xi_inp; + so = &((struct xinpcb *)xig)->xi_socket; + } + + /* Ignore sockets for protocols other than the desired one. */ + if (so->xso_protocol != proto) + continue; + + /* Ignore PCBs which were freed during copyout. */ + if (inp->inp_gencnt > oxig->xig_gen) + continue; + + if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY) + continue; + + if (first) { + printf("Active Internet connections"); + if (aflag) + printf(" (including servers)"); + putchar('\n'); + if (Aflag) + printf("%-8.8s ", "Socket"); + printf(Aflag ? + "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : + "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", + "Proto", "Recv-Q", "Send-Q", + "Local Address", "Foreign Address", "(state)"); + first = 0; + } + if (Aflag) { + if (istcp) + printf("%8lx ", (u_long)inp->inp_ppcb); + else + printf("%8lx ", (u_long)so->so_pcb); + } + printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc, + so->so_snd.sb_cc); + if (nflag) { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, + name, 1); + inetprint(&inp->inp_faddr, (int)inp->inp_fport, + name, 1); + } else if (inp->inp_flags & INP_ANONPORT) { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, + name, 1); + inetprint(&inp->inp_faddr, (int)inp->inp_fport, + name, 0); + } else { + inetprint(&inp->inp_laddr, (int)inp->inp_lport, + name, 0); + inetprint(&inp->inp_faddr, (int)inp->inp_fport, + name, inp->inp_lport != inp->inp_fport); + } + if (istcp) { + if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) + printf(" %d", tp->t_state); + else { + printf(" %s", tcpstates[tp->t_state]); +#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) + /* Show T/TCP `hidden state' */ + if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) + putchar('*'); +#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ + } + } + putchar('\n'); + } + if (xig != oxig && xig->xig_gen != oxig->xig_gen) { + if (oxig->xig_count > xig->xig_count) { + printf("Some %s sockets may have been deleted.\n", + name); + } else if (oxig->xig_count < xig->xig_count) { + printf("Some %s sockets may have been created.\n", + name); + } else { + printf("Some %s sockets may have been created or deleted", + name); + } + } + free(buf); +} + +/* + * Dump TCP statistics structure. + */ +void +tcp_stats(off, name) + u_long off; + char *name; +{ + struct tcpstat tcpstat; + size_t len = sizeof tcpstat; + + if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.tcp.stats"); + return; + } + + printf ("%s:\n", name); + +#define p(f, m) if (tcpstat.f || sflag <= 1) \ + printf(m, tcpstat.f, plural(tcpstat.f)) +#define p1a(f, m) if (tcpstat.f || sflag <= 1) \ + printf(m, tcpstat.f) +#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ + printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) +#define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ + printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) +#define p3(f, m) if (tcpstat.f || sflag <= 1) \ + printf(m, tcpstat.f, plurales(tcpstat.f)) + + p(tcps_sndtotal, "\t%lu packet%s sent\n"); + p2(tcps_sndpack,tcps_sndbyte, + "\t\t%lu data packet%s (%lu byte%s)\n"); + p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, + "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); + p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); + p2a(tcps_sndacks, tcps_delack, + "\t\t%lu ack-only packet%s (%lu delayed)\n"); + p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); + p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); + p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); + p(tcps_sndctrl, "\t\t%lu control packet%s\n"); + p(tcps_rcvtotal, "\t%lu packet%s received\n"); + p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); + p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); + p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); + p2(tcps_rcvpack, tcps_rcvbyte, + "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); + p2(tcps_rcvduppack, tcps_rcvdupbyte, + "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); + p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); + p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, + "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); + p2(tcps_rcvoopack, tcps_rcvoobyte, + "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); + p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, + "\t\t%lu packet%s (%lu byte%s) of data after window\n"); + p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); + p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); + p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); + p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); + p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); + p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); + p(tcps_connattempt, "\t%lu connection request%s\n"); + p(tcps_accepts, "\t%lu connection accept%s\n"); + p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); + p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); + p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); + p2(tcps_closed, tcps_drops, + "\t%lu connection%s closed (including %lu drop%s)\n"); + p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); + p(tcps_cachedrttvar, + "\t\t%lu connection%s updated cached RTT variance on close\n"); + p(tcps_cachedssthresh, + "\t\t%lu connection%s updated cached ssthresh on close\n"); + p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); + p2(tcps_rttupdated, tcps_segstimed, + "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); + p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); + p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); + p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); + p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); + p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); + p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); + p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); + p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); + p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); +#undef p +#undef p1a +#undef p2 +#undef p2a +#undef p3 +} + +/* + * Dump UDP statistics structure. + */ +void +udp_stats(off, name) + u_long off; + char *name; +{ + struct udpstat udpstat; + size_t len = sizeof udpstat; + u_long delivered; + + if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.udp.stats"); + return; + } + + printf("%s:\n", name); +#define p(f, m) if (udpstat.f || sflag <= 1) \ + printf(m, udpstat.f, plural(udpstat.f)) +#define p1a(f, m) if (udpstat.f || sflag <= 1) \ + printf(m, udpstat.f) + p(udps_ipackets, "\t%lu datagram%s received\n"); + p1a(udps_hdrops, "\t%lu with incomplete header\n"); + p1a(udps_badlen, "\t%lu with bad data length field\n"); + p1a(udps_badsum, "\t%lu with bad checksum\n"); + p1a(udps_noport, "\t%lu dropped due to no socket\n"); + p(udps_noportbcast, + "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); + p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); + p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); + delivered = udpstat.udps_ipackets - + udpstat.udps_hdrops - + udpstat.udps_badlen - + udpstat.udps_badsum - + udpstat.udps_noport - + udpstat.udps_noportbcast - + udpstat.udps_fullsock; + if (delivered || sflag <= 1) + printf("\t%lu delivered\n", delivered); + p(udps_opackets, "\t%lu datagram%s output\n"); +#undef p +#undef p1a +} + +/* + * Dump IP statistics structure. + */ +void +ip_stats(off, name) + u_long off; + char *name; +{ + struct ipstat ipstat; + size_t len = sizeof ipstat; + + if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.ip.stats"); + return; + } + + printf("%s:\n", name); + +#define p(f, m) if (ipstat.f || sflag <= 1) \ + printf(m, ipstat.f, plural(ipstat.f)) +#define p1a(f, m) if (ipstat.f || sflag <= 1) \ + printf(m, ipstat.f) + + p(ips_total, "\t%lu total packet%s received\n"); + p(ips_badsum, "\t%lu bad header checksum%s\n"); + p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); + p1a(ips_tooshort, "\t%lu with data size < data length\n"); + p1a(ips_badhlen, "\t%lu with header length < data size\n"); + p1a(ips_badlen, "\t%lu with data length < header length\n"); + p1a(ips_badoptions, "\t%lu with bad options\n"); + p1a(ips_badvers, "\t%lu with incorrect version number\n"); + p(ips_fragments, "\t%lu fragment%s received\n"); + p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); + p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); + p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); + p(ips_delivered, "\t%lu packet%s for this host\n"); + p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); + p(ips_forward, "\t%lu packet%s forwarded"); + p(ips_fastforward, " (%lu packet%s fast forwarded)"); + if (ipstat.ips_forward || sflag <= 1) + putchar('\n'); + p(ips_cantforward, "\t%lu packet%s not forwardable\n"); + p(ips_notmember, + "\t%lu packet%s received for unknown multicast group\n"); + p(ips_redirectsent, "\t%lu redirect%s sent\n"); + p(ips_localout, "\t%lu packet%s sent from this host\n"); + p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); + p(ips_odropped, + "\t%lu output packet%s dropped due to no bufs, etc.\n"); + p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); + p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); + p(ips_ofragments, "\t%lu fragment%s created\n"); + p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); +#undef p +#undef p1a +} + +static char *icmpnames[] = { + "echo reply", + "#1", + "#2", + "destination unreachable", + "source quench", + "routing redirect", + "#6", + "#7", + "echo", + "router advertisement", + "router solicitation", + "time exceeded", + "parameter problem", + "time stamp", + "time stamp reply", + "information request", + "information request reply", + "address mask request", + "address mask reply", +}; + +/* + * Dump ICMP statistics. + */ +void +icmp_stats(off, name) + u_long off; + char *name; +{ + struct icmpstat icmpstat; + int i, first; + int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */ + size_t len; + + mib[0] = CTL_NET; + mib[1] = PF_INET; + mib[2] = IPPROTO_ICMP; + mib[3] = ICMPCTL_STATS; + + len = sizeof icmpstat; + memset(&icmpstat, 0, len); + if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0) + return; /* XXX should complain, but not traditional */ + + printf("%s:\n", name); + +#define p(f, m) if (icmpstat.f || sflag <= 1) \ + printf(m, icmpstat.f, plural(icmpstat.f)) +#define p1a(f, m) if (icmpstat.f || sflag <= 1) \ + printf(m, icmpstat.f) + + p(icps_error, "\t%lu call%s to icmp_error\n"); + p(icps_oldicmp, + "\t%lu error%s not generated 'cuz old message was icmp\n"); + for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) + if (icmpstat.icps_outhist[i] != 0) { + if (first) { + printf("\tOutput histogram:\n"); + first = 0; + } + printf("\t\t%s: %lu\n", icmpnames[i], + icmpstat.icps_outhist[i]); + } + p(icps_badcode, "\t%lu message%s with bad code fields\n"); + p(icps_tooshort, "\t%lu message%s < minimum length\n"); + p(icps_checksum, "\t%lu bad checksum%s\n"); + p(icps_badlen, "\t%lu message%s with bad length\n"); + p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); + p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); + for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) + if (icmpstat.icps_inhist[i] != 0) { + if (first) { + printf("\tInput histogram:\n"); + first = 0; + } + printf("\t\t%s: %lu\n", icmpnames[i], + icmpstat.icps_inhist[i]); + } + p(icps_reflect, "\t%lu message response%s generated\n"); +#undef p +#undef p1a + mib[3] = ICMPCTL_MASKREPL; + len = sizeof i; + if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0) + return; + printf("\tICMP address mask responses are %sabled\n", + i ? "en" : "dis"); +} + +/* + * Dump IGMP statistics structure. + */ +void +igmp_stats(off, name) + u_long off; + char *name; +{ + struct igmpstat igmpstat; + size_t len = sizeof igmpstat; + + if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) { + warn("sysctl: net.inet.igmp.stats"); + return; + } + + printf("%s:\n", name); + +#define p(f, m) if (igmpstat.f || sflag <= 1) \ + printf(m, igmpstat.f, plural(igmpstat.f)) +#define py(f, m) if (igmpstat.f || sflag <= 1) \ + printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") + p(igps_rcv_total, "\t%u message%s received\n"); + p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); + p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); + py(igps_rcv_queries, "\t%u membership quer%s received\n"); + py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); + p(igps_rcv_reports, "\t%u membership report%s received\n"); + p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); + p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); + p(igps_snd_reports, "\t%u membership report%s sent\n"); +#undef p +#undef py +} + +/* + * Pretty print an Internet address (net address + port). + */ +void +inetprint(in, port, proto,numeric) + register struct in_addr *in; + int port; + char *proto; + int numeric; +{ + struct servent *sp = 0; + char line[80], *cp; + int width; + + sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in)); + cp = index(line, '\0'); + if (!numeric && port) + sp = getservbyport((int)port, proto); + if (sp || port == 0) + sprintf(cp, "%.15s", sp ? sp->s_name : "*"); + else + sprintf(cp, "%d", ntohs((u_short)port)); + width = Aflag ? 18 : 22; + printf(" %-*.*s", width, width, line); +} + +/* + * Construct an Internet address representation. + * If the nflag has been supplied, give + * numeric value, otherwise try for symbolic name. + */ +char * +inetname(inp) + struct in_addr *inp; +{ + register char *cp; + static char line[MAXHOSTNAMELEN + 1]; + struct hostent *hp; + struct netent *np; + + cp = 0; + if (!nflag && inp->s_addr != INADDR_ANY) { + int net = inet_netof(*inp); + int lna = inet_lnaof(*inp); + + if (lna == INADDR_ANY) { + np = getnetbyaddr(net, AF_INET); + if (np) + cp = np->n_name; + } + if (cp == 0) { + hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); + if (hp) { + cp = hp->h_name; + trimdomain(cp); + } + } + } + if (inp->s_addr == INADDR_ANY) + strcpy(line, "*"); + else if (cp) { + strncpy(line, cp, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; + } else { + inp->s_addr = ntohl(inp->s_addr); +#define C(x) ((u_int)((x) & 0xff)) + sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24), + C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); + } + return (line); +} diff --git a/netstat.tproj/iso.c b/netstat.tproj/iso.c new file mode 100644 index 0000000..526e790 --- /dev/null +++ b/netstat.tproj/iso.c @@ -0,0 +1,866 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)iso.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * $Header: /cvs/Darwin/Commands/NeXT/network_cmds/netstat.tproj/iso.c,v 1.1.1.2 2000/01/11 01:48:52 wsanchez Exp $ + * $Source: /cvs/Darwin/Commands/NeXT/network_cmds/netstat.tproj/iso.c,v $ + */ +/******************************************************************************* + Copyright IBM Corporation 1987 + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of IBM not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL +IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +*******************************************************************************/ + +/* + * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef satosiso +#include +#include +#include +#include +#include +#include +#include +#ifdef IncStat +#undef IncStat +#endif +#include +#include +#include +#include +#include +#include +#include "netstat.h" + +static void tprintstat __P((struct tp_stat *, int)); +static void isonetprint __P((struct sockaddr_iso *, int)); +static void hexprint __P((int, char *, char *)); +extern void inetprint __P((struct in_addr *, int, char *)); + +/* + * Dump esis stats + */ +void +esis_stats(off, name) + u_long off; + char *name; +{ + struct esis_stat esis_stat; + + if (off == 0 || + kread(off, (char *)&esis_stat, sizeof (struct esis_stat))) + return; + printf("%s:\n", name); + printf("\t%d esh sent, %d esh received\n", esis_stat.es_eshsent, + esis_stat.es_eshrcvd); + printf("\t%d ish sent, %d ish received\n", esis_stat.es_ishsent, + esis_stat.es_ishrcvd); + printf("\t%d rd sent, %d rd received\n", esis_stat.es_rdsent, + esis_stat.es_rdrcvd); + printf("\t%d pdus not sent due to insufficient memory\n", + esis_stat.es_nomem); + printf("\t%d pdus received with bad checksum\n", esis_stat.es_badcsum); + printf("\t%d pdus received with bad version number\n", + esis_stat.es_badvers); + printf("\t%d pdus received with bad type field\n", esis_stat.es_badtype); + printf("\t%d short pdus received\n", esis_stat.es_toosmall); +} + +/* + * Dump clnp statistics structure. + */ +void +clnp_stats(off, name) + u_long off; + char *name; +{ + struct clnp_stat clnp_stat; + + if (off == 0 || + kread(off, (char *)&clnp_stat, sizeof (clnp_stat))) + return; + + printf("%s:\n\t%d total packets sent\n", name, clnp_stat.cns_sent); + printf("\t%d total fragments sent\n", clnp_stat.cns_fragments); + printf("\t%d total packets received\n", clnp_stat.cns_total); + printf("\t%d with fixed part of header too small\n", + clnp_stat.cns_toosmall); + printf("\t%d with header length not reasonable\n", clnp_stat.cns_badhlen); + printf("\t%d incorrect checksum%s\n", + clnp_stat.cns_badcsum, plural(clnp_stat.cns_badcsum)); + printf("\t%d with unreasonable address lengths\n", clnp_stat.cns_badaddr); + printf("\t%d with forgotten segmentation information\n", + clnp_stat.cns_noseg); + printf("\t%d with an incorrect protocol identifier\n", clnp_stat.cns_noproto); + printf("\t%d with an incorrect version\n", clnp_stat.cns_badvers); + printf("\t%d dropped because the ttl has expired\n", + clnp_stat.cns_ttlexpired); + printf("\t%d clnp cache misses\n", clnp_stat.cns_cachemiss); + printf("\t%d clnp congestion experience bits set\n", + clnp_stat.cns_congest_set); + printf("\t%d clnp congestion experience bits received\n", + clnp_stat.cns_congest_rcvd); +} +/* + * Dump CLTP statistics structure. + */ +void +cltp_stats(off, name) + u_long off; + char *name; +{ + struct cltpstat cltpstat; + + if (off == 0 || + kread(off, (char *)&cltpstat, sizeof (cltpstat))) + return; + printf("%s:\n\t%u incomplete header%s\n", name, + cltpstat.cltps_hdrops, plural(cltpstat.cltps_hdrops)); + printf("\t%u bad data length field%s\n", + cltpstat.cltps_badlen, plural(cltpstat.cltps_badlen)); + printf("\t%u bad checksum%s\n", + cltpstat.cltps_badsum, plural(cltpstat.cltps_badsum)); +} + +struct tp_pcb tpcb; +struct isopcb isopcb; +static struct socket sockb; +union { + struct sockaddr_iso siso; + char data[128]; +} laddr, faddr; +#define kget(o, p) \ + (kread((u_long)(o), (char *)&p, sizeof (p))) + +static int first = 1; + +/* + * Print a summary of connections related to an Internet + * protocol. For TP, also give state of connection. + * Listening processes (aflag) are suppressed unless the + * -a (all) flag is specified. + */ +void +iso_protopr(off, name) + u_long off; + char *name; +{ + struct isopcb cb; + register struct isopcb *prev, *next; + + if (off == 0) { + printf("%s control block: symbol not in namelist\n", name); + return; + } + if (strcmp(name, "tp") == 0) { + tp_protopr(off, name); + return; + } + if (kread(off, (char *)&cb, sizeof(cb))) + return; + isopcb = cb; + prev = (struct isopcb *)off; + if (isopcb.isop_next == (struct isopcb *)off) + return; + while (isopcb.isop_next != (struct isopcb *)off) { + next = isopcb.isop_next; + kget(next, isopcb); + if (isopcb.isop_prev != prev) { + printf("prev 0x%x next 0x%x isop_prev 0x%x isop_next 0x%x???\n", + prev, next, isopcb.isop_prev, isopcb.isop_next); + break; + } + kget(isopcb.isop_socket, sockb); + iso_protopr1((u_long)next, 0); + putchar('\n'); + prev = next; + } +} + +void +iso_protopr1(kern_addr, istp) + u_long kern_addr; + int istp; +{ + if (first) { + printf("Active ISO net connections"); + if (aflag) + printf(" (including servers)"); + putchar('\n'); + if (Aflag) + printf("%-8.8s ", "PCB"); + printf(Aflag ? + "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : + "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", + "Proto", "Recv-Q", "Send-Q", + "Local Address", "Foreign Address", "(state)"); + first = 0; + } + if (Aflag) + printf("%8x ", + (sockb.so_pcb ? (void *)sockb.so_pcb : (void *)kern_addr)); + printf("%-5.5s %6d %6d ", "tp", sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc); + if (istp && tpcb.tp_lsuffixlen) { + hexprint(tpcb.tp_lsuffixlen, tpcb.tp_lsuffix, "()"); + printf("\t"); + } else if (isopcb.isop_laddr == 0) + printf("*.*\t"); + else { + if ((char *)isopcb.isop_laddr == ((char *)kern_addr) + + _offsetof(struct isopcb, isop_sladdr)) + laddr.siso = isopcb.isop_sladdr; + else + kget(isopcb.isop_laddr, laddr); + isonetprint((struct sockaddr_iso *)&laddr, 1); + } + if (istp && tpcb.tp_fsuffixlen) { + hexprint(tpcb.tp_fsuffixlen, tpcb.tp_fsuffix, "()"); + printf("\t"); + } else if (isopcb.isop_faddr == 0) + printf("*.*\t"); + else { + if ((char *)isopcb.isop_faddr == ((char *)kern_addr) + + _offsetof(struct isopcb, isop_sfaddr)) + faddr.siso = isopcb.isop_sfaddr; + else + kget(isopcb.isop_faddr, faddr); + isonetprint((struct sockaddr_iso *)&faddr, 0); + } +} + +void +tp_protopr(off, name) + u_long off; + char *name; +{ + extern char *tp_sstring[]; + struct tp_ref *tpr, *tpr_base; + struct tp_refinfo tpkerninfo; + int size; + + kget(off, tpkerninfo); + size = tpkerninfo.tpr_size * sizeof (*tpr); + tpr_base = (struct tp_ref *)malloc(size); + if (tpr_base == 0) + return; + kread((u_long)(tpkerninfo.tpr_base), (char *)tpr_base, size); + for (tpr = tpr_base; tpr < tpr_base + tpkerninfo.tpr_size; tpr++) { + if (tpr->tpr_pcb == 0) + continue; + kget(tpr->tpr_pcb, tpcb); + if (tpcb.tp_state == ST_ERROR) + printf("undefined tpcb state: 0x%x\n", tpr->tpr_pcb); + if (!aflag && + (tpcb.tp_state == TP_LISTENING || + tpcb.tp_state == TP_CLOSED || + tpcb.tp_state == TP_REFWAIT)) { + continue; + } + kget(tpcb.tp_sock, sockb); + if (tpcb.tp_npcb) switch(tpcb.tp_netservice) { + case IN_CLNS: + tp_inproto((u_long)tpkerninfo.tpr_base); + break; + default: + kget(tpcb.tp_npcb, isopcb); + iso_protopr1((u_long)tpcb.tp_npcb, 1); + break; + } + if (tpcb.tp_state >= tp_NSTATES) + printf(" %d", tpcb.tp_state); + else + printf(" %-12.12s", tp_sstring[tpcb.tp_state]); + putchar('\n'); + } +} + +void +tp_inproto(pcb) + u_long pcb; +{ + struct inpcb inpcb; + kget(tpcb.tp_npcb, inpcb); + if (!aflag && inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) + return; + if (Aflag) + printf("%8x ", pcb); + printf("%-5.5s %6d %6d ", "tpip", + sockb.so_rcv.sb_cc, sockb.so_snd.sb_cc); + inetprint(&inpcb.inp_laddr, inpcb.inp_lport, "tp"); + inetprint(&inpcb.inp_faddr, inpcb.inp_fport, "tp"); +} + +/* + * Pretty print an iso address (net address + port). + * If the nflag was specified, use numbers instead of names. + */ + +#ifdef notdef +char * +isonetname(iso) + register struct iso_addr *iso; +{ + struct sockaddr_iso sa; + struct iso_hostent *ihe = 0; + struct iso_hostent *iso_gethostentrybyaddr(); + struct iso_hostent *iso_getserventrybytsel(); + struct iso_hostent Ihe; + static char line[80]; + + bzero(line, sizeof(line)); + if( iso->isoa_afi ) { + sa.siso_family = AF_ISO; + sa.siso_addr = *iso; + sa.siso_tsuffix = 0; + + if (!nflag ) + ihe = iso_gethostentrybyaddr( &sa, 0, 0 ); + if( ihe ) { + Ihe = *ihe; + ihe = &Ihe; + sprintf(line, "%s", ihe->isoh_hname); + } else { + sprintf(line, "%s", iso_ntoa(iso)); + } + } else { + sprintf(line, "*"); + } + return line; +} + +static void +isonetprint(iso, sufx, sufxlen, islocal) + register struct iso_addr *iso; + char *sufx; + u_short sufxlen; + int islocal; +{ + struct iso_hostent *iso_getserventrybytsel(), *ihe; + struct iso_hostent Ihe; + char *line, *cp; + int Alen = Aflag?18:22; + + line = isonetname(iso); + cp = index(line, '\0'); + ihe = (struct iso_hostent *)0; + + if( islocal ) + islocal = 20; + else + islocal = 22 + Alen; + + if(Aflag) + islocal += 10 ; + + if(!nflag) { + if( (cp -line)>10 ) { + cp = line+10; + bzero(cp, sizeof(line)-10); + } + } + + *cp++ = '.'; + if(sufxlen) { + if( !Aflag && !nflag && (ihe=iso_getserventrybytsel(sufx, sufxlen))) { + Ihe = *ihe; + ihe = &Ihe; + } + if( ihe && (strlen(ihe->isoh_aname)>0) ) { + sprintf(cp, "%s", ihe->isoh_aname); + } else { + iso_sprinttsel(cp, sufx, sufxlen); + } + } else + sprintf(cp, "*"); + /* + fprintf(stdout, Aflag?" %-18.18s":" %-22.22s", line); + */ + + if( strlen(line) > Alen ) { + fprintf(stdout, " %s", line); + fprintf(stdout, "\n %*.s", islocal+Alen," "); + } else { + fprintf(stdout, " %-*.*s", Alen, Alen,line); + } +} +#endif + +#ifdef notdef +static void +x25_protopr(off, name) + u_long off; + char *name; +{ + static char *xpcb_states[] = { + "CLOSED", + "LISTENING", + "CLOSING", + "CONNECTING", + "ACKWAIT", + "OPEN", + }; + register struct isopcb *prev, *next; + struct x25_pcb xpcb; + + if (off == 0) { + printf("%s control block: symbol not in namelist\n", name); + return; + } + kread(off, &xpcb, sizeof (struct x25_pcb)); + prev = (struct isopcb *)off; + if (xpcb.x_next == (struct isopcb *)off) + return; + while (xpcb.x_next != (struct isopcb *)off) { + next = isopcb.isop_next; + kread((u_long)next, &xpcb, sizeof (struct x25_pcb)); + if (xpcb.x_prev != prev) { + printf("???\n"); + break; + } + kread((u_long)xpcb.x_socket, &sockb, sizeof (sockb)); + + if (!aflag && + xpcb.x_state == LISTENING || + xpcb.x_state == TP_CLOSED ) { + prev = next; + continue; + } + if (first) { + printf("Active X25 net connections"); + if (aflag) + printf(" (including servers)"); + putchar('\n'); + if (Aflag) + printf("%-8.8s ", "PCB"); + printf(Aflag ? + "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : + "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", + "Proto", "Recv-Q", "Send-Q", + "Local Address", "Foreign Address", "(state)"); + first = 0; + } + printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc, + sockb.so_snd.sb_cc); + isonetprint(&xpcb.x_laddr.siso_addr, &xpcb.x_lport, + sizeof(xpcb.x_lport), 1); + isonetprint(&xpcb.x_faddr.siso_addr, &xpcb.x_fport, + sizeof(xpcb.x_lport), 0); + if (xpcb.x_state < 0 || xpcb.x_state >= x25_NSTATES) + printf(" 0x0x0x0x0x0x0x0x0x%x", xpcb.x_state); + else + printf(" %-12.12s", xpcb_states[xpcb.x_state]); + putchar('\n'); + prev = next; + } +} +#endif + +struct tp_stat tp_stat; + +void +tp_stats(off, name) + caddr_t off, name; +{ + if (off == 0) { + printf("TP not configured\n\n"); + return; + } + printf("%s:\n", name); + kget(off, tp_stat); + tprintstat(&tp_stat, 8); +} + +#define OUT stdout + +static void +tprintstat(s, indent) + register struct tp_stat *s; + int indent; +{ + fprintf(OUT, + "%*sReceiving:\n",indent," "); + fprintf(OUT, + "\t%*s%d variable parameter%s ignored\n", indent," ", + s->ts_param_ignored ,plural(s->ts_param_ignored)); + fprintf(OUT, + "\t%*s%d invalid parameter code%s\n", indent, " ", + s->ts_inv_pcode ,plural(s->ts_inv_pcode)); + fprintf(OUT, + "\t%*s%d invalid parameter value%s\n", indent, " ", + s->ts_inv_pval ,plural(s->ts_inv_pval)); + fprintf(OUT, + "\t%*s%d invalid dutype%s\n", indent, " ", + s->ts_inv_dutype ,plural(s->ts_inv_dutype)); + fprintf(OUT, + "\t%*s%d negotiation failure%s\n", indent, " ", + s->ts_negotfailed ,plural(s->ts_negotfailed)); + fprintf(OUT, + "\t%*s%d invalid destination reference%s\n", indent, " ", + s->ts_inv_dref ,plural(s->ts_inv_dref)); + fprintf(OUT, + "\t%*s%d invalid suffix parameter%s\n", indent, " ", + s->ts_inv_sufx ,plural(s->ts_inv_sufx)); + fprintf(OUT, + "\t%*s%d invalid length\n",indent, " ", s->ts_inv_length); + fprintf(OUT, + "\t%*s%d invalid checksum%s\n", indent, " ", + s->ts_bad_csum ,plural(s->ts_bad_csum)); + fprintf(OUT, + "\t%*s%d DT%s out of order\n", indent, " ", + s->ts_dt_ooo ,plural(s->ts_dt_ooo)); + fprintf(OUT, + "\t%*s%d DT%s not in window\n", indent, " ", + s->ts_dt_niw ,plural(s->ts_dt_niw)); + fprintf(OUT, + "\t%*s%d duplicate DT%s\n", indent, " ", + s->ts_dt_dup ,plural(s->ts_dt_dup)); + fprintf(OUT, + "\t%*s%d XPD%s not in window\n", indent, " ", + s->ts_xpd_niw ,plural(s->ts_xpd_niw)); + fprintf(OUT, + "\t%*s%d XPD%s w/o credit to stash\n", indent, " ", + s->ts_xpd_dup ,plural(s->ts_xpd_dup)); + fprintf(OUT, + "\t%*s%d time%s local credit reneged\n", indent, " ", + s->ts_lcdt_reduced ,plural(s->ts_lcdt_reduced)); + fprintf(OUT, + "\t%*s%d concatenated TPDU%s\n", indent, " ", + s->ts_concat_rcvd ,plural(s->ts_concat_rcvd)); + fprintf(OUT, + "%*sSending:\n", indent, " "); + fprintf(OUT, + "\t%*s%d XPD mark%s discarded\n", indent, " ", + s->ts_xpdmark_del ,plural(s->ts_xpdmark_del)); + fprintf(OUT, + "\t%*sXPD stopped data flow %d time%s\n", indent, " ", + s->ts_xpd_intheway ,plural(s->ts_xpd_intheway)); + fprintf(OUT, + "\t%*s%d time%s foreign window closed\n", indent, " ", + s->ts_zfcdt ,plural(s->ts_zfcdt)); + fprintf(OUT, + "%*sMiscellaneous:\n", indent, " "); + fprintf(OUT, + "\t%*s%d small mbuf%s\n", indent, " ", + s->ts_mb_small ,plural(s->ts_mb_small)); + fprintf(OUT, + "\t%*s%d cluster%s\n", indent, " ", + s->ts_mb_cluster, plural(s->ts_mb_cluster)); + fprintf(OUT, + "\t%*s%d source quench \n",indent, " ", + s->ts_quench); + fprintf(OUT, + "\t%*s%d dec bit%s\n", indent, " ", + s->ts_rcvdecbit, plural(s->ts_rcvdecbit)); + fprintf(OUT, + "\t%*sM:L ( M mbuf chains of length L)\n", indent, " "); + { + register int j; + + fprintf(OUT, "\t%*s%d: over 16\n", indent, " ", + s->ts_mb_len_distr[0]); + for( j=1; j<=8; j++) { + fprintf(OUT, + "\t%*s%d: %d\t\t%d: %d\n", indent, " ", + s->ts_mb_len_distr[j],j, + s->ts_mb_len_distr[j<<1],j<<1 + ); + } + } + fprintf(OUT, + "\t%*s%d EOT rcvd\n", indent, " ", s->ts_eot_input); + fprintf(OUT, + "\t%*s%d EOT sent\n", indent, " ", s->ts_EOT_sent); + fprintf(OUT, + "\t%*s%d EOT indication%s\n", indent, " ", + s->ts_eot_user ,plural(s->ts_eot_user)); + + fprintf(OUT, + "%*sConnections:\n", indent, " "); + fprintf(OUT, + "\t%*s%d connection%s used extended format\n", indent, " ", + s->ts_xtd_fmt ,plural(s->ts_xtd_fmt)); + fprintf(OUT, + "\t%*s%d connection%s allowed transport expedited data\n", indent, " ", + s->ts_use_txpd ,plural(s->ts_use_txpd)); + fprintf(OUT, + "\t%*s%d connection%s turned off checksumming\n", indent, " ", + s->ts_csum_off ,plural(s->ts_csum_off)); + fprintf(OUT, + "\t%*s%d connection%s dropped due to retrans limit\n", indent, " ", + s->ts_conn_gaveup ,plural(s->ts_conn_gaveup)); + fprintf(OUT, + "\t%*s%d tp 4 connection%s\n", indent, " ", + s->ts_tp4_conn ,plural(s->ts_tp4_conn)); + fprintf(OUT, + "\t%*s%d tp 0 connection%s\n", indent, " ", + s->ts_tp0_conn ,plural(s->ts_tp0_conn)); + { + register int j; + static char *name[]= { + "~LOCAL, PDN", + "~LOCAL,~PDN", + " LOCAL,~PDN", + " LOCAL, PDN" + }; + + fprintf(OUT, + "\n%*sRound trip times, listed in ticks:\n", indent, " "); + fprintf(OUT, + "\t%*s%11.11s %12.12s | %12.12s | %s\n", indent, " ", + "Category", + "Smoothed avg", "Deviation", "Deviation/Avg"); + for (j = 0; j <= 3; j++) { + fprintf(OUT, + "\t%*s%11.11s: %-11d | %-11d | %-11d | %-11d\n", indent, " ", + name[j], + s->ts_rtt[j], + s->ts_rtt[j], + s->ts_rtv[j], + s->ts_rtv[j]); + } + } + fprintf(OUT, +"\n%*sTpdus RECVD [%d valid, %3.6f %% of total (%d); %d dropped]\n",indent," ", + s->ts_tpdu_rcvd , + ((s->ts_pkt_rcvd > 0) ? + ((100 * (float)s->ts_tpdu_rcvd)/(float)s->ts_pkt_rcvd) + : 0), + s->ts_pkt_rcvd, + s->ts_recv_drop ); + + fprintf(OUT, + "\t%*sDT %6d AK %6d DR %4d CR %4d \n", indent, " ", + s->ts_DT_rcvd, s->ts_AK_rcvd, s->ts_DR_rcvd, s->ts_CR_rcvd); + fprintf(OUT, + "\t%*sXPD %6d XAK %6d DC %4d CC %4d ER %4d\n", indent, " ", + s->ts_XPD_rcvd, s->ts_XAK_rcvd, s->ts_DC_rcvd, s->ts_CC_rcvd, + s->ts_ER_rcvd); + fprintf(OUT, + "\n%*sTpdus SENT [%d total, %d dropped]\n", indent, " ", + s->ts_tpdu_sent, s->ts_send_drop); + + fprintf(OUT, + "\t%*sDT %6d AK %6d DR %4d CR %4d \n", indent, " ", + s->ts_DT_sent, s->ts_AK_sent, s->ts_DR_sent, s->ts_CR_sent); + fprintf(OUT, + "\t%*sXPD %6d XAK %6d DC %4d CC %4d ER %4d\n", indent, " ", + s->ts_XPD_sent, s->ts_XAK_sent, s->ts_DC_sent, s->ts_CC_sent, + s->ts_ER_sent); + + fprintf(OUT, + "\n%*sRetransmissions:\n", indent, " "); +#define PERCENT(X,Y) (((Y)>0)?((100 *(float)(X)) / (float) (Y)):0) + + fprintf(OUT, + "\t%*sCR %6d CC %6d DR %6d \n", indent, " ", + s->ts_retrans_cr, s->ts_retrans_cc, s->ts_retrans_dr); + fprintf(OUT, + "\t%*sDT %6d (%5.2f%%)\n", indent, " ", + s->ts_retrans_dt, + PERCENT(s->ts_retrans_dt, s->ts_DT_sent)); + fprintf(OUT, + "\t%*sXPD %6d (%5.2f%%)\n", indent, " ", + s->ts_retrans_xpd, + PERCENT(s->ts_retrans_xpd, s->ts_XPD_sent)); + + + fprintf(OUT, + "\n%*sE Timers: [%6d ticks]\n", indent, " ", s->ts_Eticks); + fprintf(OUT, + "%*s%6d timer%s set \t%6d timer%s expired \t%6d timer%s cancelled\n",indent, " ", + s->ts_Eset ,plural(s->ts_Eset), + s->ts_Eexpired ,plural(s->ts_Eexpired), + s->ts_Ecan_act ,plural(s->ts_Ecan_act)); + + fprintf(OUT, + "\n%*sC Timers: [%6d ticks]\n", indent, " ",s->ts_Cticks); + fprintf(OUT, + "%*s%6d timer%s set \t%6d timer%s expired \t%6d timer%s cancelled\n", + indent, " ", + s->ts_Cset ,plural(s->ts_Cset), + s->ts_Cexpired ,plural(s->ts_Cexpired), + s->ts_Ccan_act ,plural(s->ts_Ccan_act)); + fprintf(OUT, + "%*s%6d inactive timer%s cancelled\n", indent, " ", + s->ts_Ccan_inact ,plural(s->ts_Ccan_inact)); + + fprintf(OUT, + "\n%*sPathological debugging activity:\n", indent, " "); + fprintf(OUT, + "\t%*s%6d CC%s sent to zero dref\n", indent, " ", + s->ts_zdebug ,plural(s->ts_zdebug)); + /* SAME LINE AS ABOVE */ + fprintf(OUT, + "\t%*s%6d random DT%s dropped\n", indent, " ", + s->ts_ydebug ,plural(s->ts_ydebug)); + fprintf(OUT, + "\t%*s%6d illegally large XPD TPDU%s\n", indent, " ", + s->ts_vdebug ,plural(s->ts_vdebug)); + fprintf(OUT, + "\t%*s%6d faked reneging of cdt\n", indent, " ", + s->ts_ldebug ); + + fprintf(OUT, + "\n%*sACK reasons:\n", indent, " "); + fprintf(OUT, "\t%*s%6d not acked immediately\n", indent, " ", + s->ts_ackreason[_ACK_DONT_] ); + fprintf(OUT, "\t%*s%6d strategy==each\n", indent, " ", + s->ts_ackreason[_ACK_STRAT_EACH_] ); + fprintf(OUT, "\t%*s%6d strategy==fullwindow\n", indent, " ", + s->ts_ackreason[_ACK_STRAT_FULLWIN_] ); + fprintf(OUT, "\t%*s%6d duplicate DT\n", indent, " ", + s->ts_ackreason[_ACK_DUP_] ); + fprintf(OUT, "\t%*s%6d EOTSDU\n", indent, " ", + s->ts_ackreason[_ACK_EOT_] ); + fprintf(OUT, "\t%*s%6d reordered DT\n", indent, " ", + s->ts_ackreason[_ACK_REORDER_] ); + fprintf(OUT, "\t%*s%6d user rcvd\n", indent, " ", + s->ts_ackreason[_ACK_USRRCV_] ); + fprintf(OUT, "\t%*s%6d fcc reqd\n", indent, " ", + s->ts_ackreason[_ACK_FCC_] ); +} +#ifndef SSEL +#define SSEL(s) ((s)->siso_tlen + TSEL(s)) +#define PSEL(s) ((s)->siso_slen + SSEL(s)) +#endif + +static void +isonetprint(siso, islocal) + register struct sockaddr_iso *siso; + int islocal; +{ + hexprint(siso->siso_nlen, siso->siso_addr.isoa_genaddr, "{}"); + if (siso->siso_tlen || siso->siso_slen || siso->siso_plen) + hexprint(siso->siso_tlen, TSEL(siso), "()"); + if (siso->siso_slen || siso->siso_plen) + hexprint(siso->siso_slen, SSEL(siso), "[]"); + if (siso->siso_plen) + hexprint(siso->siso_plen, PSEL(siso), "<>"); + putchar(' '); +} + +static char hexlist[] = "0123456789abcdef", obuf[128]; + +static void +hexprint(n, buf, delim) + int n; + char *buf, *delim; +{ + register u_char *in = (u_char *)buf, *top = in + n; + register char *out = obuf; + register int i; + + if (n == 0) + return; + while (in < top) { + i = *in++; + *out++ = '.'; + if (i > 0xf) { + out[1] = hexlist[i & 0xf]; + i >>= 4; + out[0] = hexlist[i]; + out += 2; + } else + *out++ = hexlist[i]; + } + *obuf = *delim; *out++ = delim[1]; *out = 0; + printf("%s", obuf); +} diff --git a/netstat.tproj/main.c b/netstat.tproj/main.c new file mode 100644 index 0000000..8ca3a72 --- /dev/null +++ b/netstat.tproj/main.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char const copyright[] = +"@(#) Copyright (c) 1983, 1988, 1993\n\ + Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94"; +#endif +static const char rcsid[] = + "$Id: main.c,v 1.2 2000/06/16 03:37:29 lindak Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "netstat.h" +#include +#include + + +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $Id: main.c,v 1.2 2000/06/16 03:37:29 lindak Exp $ + * + */ + + +static struct nlist nl[] = { +#define N_IFNET 0 + { "_ifnet" }, +#define N_IMP 1 + { "_imp_softc" }, +#define N_RTSTAT 2 + { "_rtstat" }, +#define N_UNIXSW 3 + { "_localsw" }, +#define N_IDP 4 + { "_nspcb"}, +#define N_IDPSTAT 5 + { "_idpstat"}, +#define N_SPPSTAT 6 + { "_spp_istat"}, +#define N_NSERR 7 + { "_ns_errstat"}, +#define N_CLNPSTAT 8 + { "_clnp_stat"}, +#define IN_NOTUSED 9 + { "_tp_inpcb" }, +#define ISO_TP 10 + { "_tp_refinfo" }, +#define N_TPSTAT 11 + { "_tp_stat" }, +#define N_ESISSTAT 12 + { "_esis_stat"}, +#define N_NIMP 13 + { "_nimp"}, +#define N_RTREE 14 + { "_rt_tables"}, +#define N_CLTP 15 + { "_cltb"}, +#define N_CLTPSTAT 16 + { "_cltpstat"}, +#define N_NFILE 17 + { "_nfile" }, +#define N_FILE 18 + { "_file" }, +#define N_MRTSTAT 19 + { "_mrtstat" }, +#define N_MFCTABLE 20 + { "_mfctable" }, +#define N_VIFTABLE 21 + { "_viftable" }, +#define N_IPX 22 + { "_ipxpcb"}, +#define N_IPXSTAT 23 + { "_ipxstat"}, +#define N_SPXSTAT 24 + { "_spx_istat"}, +#define N_DDPSTAT 25 + { "_ddpstat"}, +#define N_DDPCB 26 + { "_ddpcb"}, +#define N_MBSTAT 27 + {"_mbstat"}, + { "" }, +}; + + + +struct protox { + u_char pr_index; /* index into nlist of cb head */ + u_char pr_sindex; /* index into nlist of stat block */ + u_char pr_wanted; /* 1 if wanted, 0 otherwise */ + void (*pr_cblocks)(); /* control blocks printing routine */ + void (*pr_stats)(); /* statistics printing routine */ + char *pr_name; /* well-known name */ + int pr_usesysctl; /* true if we use sysctl, not kvm */ +} protox[] = { + { -1, -1, 1, protopr, + tcp_stats, "tcp", IPPROTO_TCP }, + { -1, -1, 1, protopr, + udp_stats, "udp", IPPROTO_UDP }, + { -1, -1, 1, protopr, + NULL, "divert", IPPROTO_DIVERT }, + { -1, -1, 1, protopr, + ip_stats, "ip", IPPROTO_RAW }, + { -1, -1, 1, protopr, + icmp_stats, "icmp", IPPROTO_ICMP }, + { -1, -1, 1, protopr, + igmp_stats, "igmp", IPPROTO_IGMP }, + { -1, -1, 0, 0, + 0, 0 } +}; + +#ifdef UNIX_ATALK +struct protox atalkprotox[] = { + { N_DDPCB, N_DDPSTAT, 1, atalkprotopr, + ddp_stats, "ddp" }, + { -1, -1, 0, 0, + 0, 0 } +}; +#endif + +#ifdef IPX +struct protox ipxprotox[] = { + { N_IPX, N_IPXSTAT, 1, ipxprotopr, + ipx_stats, "ipx", 0 }, + { N_IPX, N_SPXSTAT, 1, ipxprotopr, + spx_stats, "spx", 0 }, + { -1, -1, 0, 0, + 0, 0, 0 } +}; +#endif + +#ifdef NS +struct protox nsprotox[] = { + { N_IDP, N_IDPSTAT, 1, nsprotopr, + idp_stats, "idp" }, + { N_IDP, N_SPPSTAT, 1, nsprotopr, + spp_stats, "spp" }, + { -1, N_NSERR, 1, 0, + nserr_stats, "ns_err" }, + { -1, -1, 0, 0, + 0, 0 } +}; +#endif + +#ifdef ISO +struct protox isoprotox[] = { + { ISO_TP, N_TPSTAT, 1, iso_protopr, + tp_stats, "tp" }, + { N_CLTP, N_CLTPSTAT, 1, iso_protopr, + cltp_stats, "cltp" }, + { -1, N_CLNPSTAT, 1, 0, + clnp_stats, "clnp"}, + { -1, N_ESISSTAT, 1, 0, + esis_stats, "esis"}, + { -1, -1, 0, 0, + 0, 0 } +}; +#endif + +struct protox *protoprotox[] = { protox, + +#ifdef IPX +ipxprotox, +#endif + +#ifdef UNIX_ATALK +atalkprotox, +#endif + +#ifdef NS + nsprotox, +#endif +#ifdef ISO + isoprotox, +#endif + NULL }; + +static void printproto __P((struct protox *, char *)); +static void usage __P((void)); +static struct protox *name2protox __P((char *)); +static struct protox *knownname __P((char *)); + +static kvm_t *kvmd; +char *nlistf = NULL, *memf = NULL; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register struct protoent *p; + register struct protox *tp; /* for printing cblocks & stats */ + int ch; + + af = AF_UNSPEC; + + while ((ch = getopt(argc, argv, "Aabdf:ghI:iM:mN:np:rstuw:")) != -1) + switch(ch) { + case 'A': + Aflag = 1; + break; + case 'a': + aflag = 1; + break; + case 'b': + bflag = 1; + break; + case 'd': + dflag = 1; + break; + case 'f': +#ifdef NS + if (strcmp(optarg, "ns") == 0) + af = AF_NS; + else +#endif + if (strcmp(optarg, "ipx") == 0) + af = AF_IPX; + else if (strcmp(optarg, "inet") == 0) + af = AF_INET; + else if (strcmp(optarg, "unix") == 0) + af = AF_UNIX; + else if (strcmp(optarg, "local") == 0) + af = AF_LOCAL; + else if (strcmp(optarg, "atalk") == 0) + af = AF_APPLETALK; +#ifdef ISO + else if (strcmp(optarg, "iso") == 0) + af = AF_ISO; +#endif + else { + errx(1, "%s: unknown address family", optarg); + } + break; + case 'g': + gflag = 1; + break; + case 'I': { + char *cp; + + iflag = 1; + for (cp = interface = optarg; isalpha(*cp); cp++) + continue; + unit = atoi(cp); + break; + } + case 'i': + iflag = 1; + break; + case 'M': + memf = optarg; + break; + case 'm': + mflag = 1; + break; + case 'N': + nlistf = optarg; + break; + case 'n': + nflag = 1; + break; + case 'p': + if ((tp = name2protox(optarg)) == NULL) { + errx(1, + "%s: unknown or uninstrumented protocol", + optarg); + } + pflag = 1; + break; + case 'r': + rflag = 1; + break; + case 's': + ++sflag; + break; + case 't': + tflag = 1; + break; + case 'u': + af = AF_UNIX; + break; + case 'w': + interval = atoi(optarg); + iflag = 1; + break; + case '?': + default: + usage(); + } + argv += optind; + argc -= optind; + +#define BACKWARD_COMPATIBILITY +#ifdef BACKWARD_COMPATIBILITY + if (*argv) { + if (isdigit(**argv)) { + interval = atoi(*argv); + if (interval <= 0) + usage(); + ++argv; + iflag = 1; + } + if (*argv) { + nlistf = *argv; + if (*++argv) + memf = *argv; + } + } +#endif + + /* + * Discard setgid privileges if not the running kernel so that bad + * guys can't print interesting stuff from kernel memory. + */ + if (nlistf != NULL || memf != NULL) + setgid(getgid()); + + if (mflag) { + kread(0,0,0); + mbpr(nl[N_MBSTAT].n_value); + exit(0); + } + if (pflag) { + if (!tp->pr_stats) { + printf("%s: no stats routine\n", tp->pr_name); + exit(0); + } + if (tp->pr_usesysctl) { + (*tp->pr_stats)(tp->pr_usesysctl, tp->pr_name); + } else { + kread(0, 0, 0); + (*tp->pr_stats)(nl[tp->pr_sindex].n_value, + tp->pr_name); + } + exit(0); + } +#if 0 + /* + * Keep file descriptors open to avoid overhead + * of open/close on each call to get* routines. + */ + sethostent(1); + setnetent(1); +#else + /* + * This does not make sense any more with DNS being default over + * the files. Doing a setXXXXent(1) causes a tcp connection to be + * used for the queries, which is slower. + */ +#endif + if (iflag) { + kread(0, 0, 0); + intpr(interval, nl[N_IFNET].n_value); + exit(0); + } + if (rflag) { + kread(0, 0, 0); + if (sflag) + rt_stats(nl[N_RTSTAT].n_value); + else + routepr(nl[N_RTREE].n_value); + exit(0); + } + if (gflag) { + kread(0, 0, 0); + if (sflag) + mrt_stats(nl[N_MRTSTAT].n_value); + else + mroutepr(nl[N_MFCTABLE].n_value, + nl[N_VIFTABLE].n_value); + exit(0); + } + if (af == AF_INET || af == AF_UNSPEC) { + setprotoent(1); + setservent(1); + /* ugh, this is O(MN) ... why do we do this? */ + while ((p = getprotoent())) { + for (tp = protox; tp->pr_name; tp++) + if (strcmp(tp->pr_name, p->p_name) == 0) + break; + if (tp->pr_name == 0 || tp->pr_wanted == 0) + continue; + printproto(tp, p->p_name); + } + endprotoent(); + } + +#ifdef IPX + if (af == AF_IPX || af == AF_UNSPEC) { + kread(0, 0, 0); + for (tp = ipxprotox; tp->pr_name; tp++) + printproto(tp, tp->pr_name); + } +#endif +#ifdef UNIX_ATALK + if (af == AF_APPLETALK || af == AF_UNSPEC) + for (tp = atalkprotox; tp->pr_name; tp++) + printproto(tp, tp->pr_name); +#endif +#ifdef NS + if (af == AF_NS || af == AF_UNSPEC) + for (tp = nsprotox; tp->pr_name; tp++) + printproto(tp, tp->pr_name); +#endif +#ifdef ISO + if (af == AF_ISO || af == AF_UNSPEC) + for (tp = isoprotox; tp->pr_name; tp++) + printproto(tp, tp->pr_name); +#endif + if ((af == AF_UNIX || af == AF_LOCAL || af == AF_UNSPEC) && !sflag) + unixpr(); + exit(0); +} + +/* + * Print out protocol statistics or control blocks (per sflag). + * If the interface was not specifically requested, and the symbol + * is not in the namelist, ignore this one. + */ +static void +printproto(tp, name) + register struct protox *tp; + char *name; +{ + void (*pr)(); + u_long off; + + if (sflag) { + pr = tp->pr_stats; + off = tp->pr_usesysctl ? tp->pr_usesysctl + : nl[tp->pr_sindex].n_value; + } else { + pr = tp->pr_cblocks; + off = tp->pr_usesysctl ? tp->pr_usesysctl + : nl[tp->pr_index].n_value; + } + if (pr != NULL && (off || af != AF_UNSPEC)) + (*pr)(off, name); +} + +/* + * Read kernel memory, return 0 on success. + */ +int +kread(addr, buf, size) + u_long addr; + char *buf; + int size; +{ + if (kvmd == 0) { + /* + * XXX. + */ + kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf); + if (kvmd != NULL) { + if (kvm_nlist(kvmd, nl) < 0) { + if(nlistf) + errx(1, "%s: kvm_nlist: %s", nlistf, + kvm_geterr(kvmd)); + else + errx(1, "kvm_nlist: %s", kvm_geterr(kvmd)); + } + + if (nl[0].n_type == 0) { + if(nlistf) + errx(1, "%s: no namelist", nlistf); + else + errx(1, "no namelist"); + } + } else { + warnx("kvm not available"); + return(-1); + } + } + if (!buf) + return (0); + if (kvm_read(kvmd, addr, buf, size) != size) { + warnx("%s", kvm_geterr(kvmd)); + return (-1); + } + return (0); +} + +char * +plural(n) + int n; +{ + return (n != 1 ? "s" : ""); +} + +char * +plurales(n) + int n; +{ + return (n != 1 ? "es" : ""); +} + +/* + * Find the protox for the given "well-known" name. + */ +static struct protox * +knownname(name) + char *name; +{ + struct protox **tpp, *tp; + + for (tpp = protoprotox; *tpp; tpp++) + for (tp = *tpp; tp->pr_name; tp++) + if (strcmp(tp->pr_name, name) == 0) + return (tp); + return (NULL); +} + +/* + * Find the protox corresponding to name. + */ +static struct protox * +name2protox(name) + char *name; +{ + struct protox *tp; + char **alias; /* alias from p->aliases */ + struct protoent *p; + + /* + * Try to find the name in the list of "well-known" names. If that + * fails, check if name is an alias for an Internet protocol. + */ + if ((tp = knownname(name))) + return (tp); + + setprotoent(1); /* make protocol lookup cheaper */ + while ((p = getprotoent())) { + /* assert: name not same as p->name */ + for (alias = p->p_aliases; *alias; alias++) + if (strcmp(name, *alias) == 0) { + endprotoent(); + return (knownname(p->p_name)); + } + } + endprotoent(); + return (NULL); +} + +static void +usage() +{ + (void)fprintf(stderr, "%s\n%s\n%s\n%s\n", +"usage: netstat [-Aan] [-f address_family] [-M core] [-N system]", +" netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]", +" netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]", +" netstat [-M core] [-N system] [-p protocol]"); + exit(1); +} + +void +trimdomain(cp) + char *cp; +{ + static char domain[MAXHOSTNAMELEN + 1]; + static int first = 1; + char *s; + + if (first) { + first = 0; + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (s = strchr(domain, '.'))) + (void) strcpy(domain, s + 1); + else + domain[0] = 0; + } + + if (domain[0]) { + while ((cp = strchr(cp, '.'))) { + if (!strcasecmp(cp + 1, domain)) { + *cp = 0; /* hit it */ + break; + } else { + cp++; + } + } + } +} + diff --git a/netstat.tproj/mbuf.c b/netstat.tproj/mbuf.c new file mode 100644 index 0000000..95f81b4 --- /dev/null +++ b/netstat.tproj/mbuf.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include + +#include +#include "netstat.h" +#include /* To get Appletalk message/mbuf types */ + +#define YES 1 +typedef int bool; + +struct mbstat mbstat; + +static struct mbtypes { + int mt_type; + char *mt_name; +} mbtypes[] = { + { MT_DATA, "data" }, + { MT_OOBDATA, "oob data" }, + { MT_CONTROL, "ancillary data" }, + { MT_HEADER, "packet headers" }, + { MT_SOCKET, "socket structures" }, /* XXX */ + { MT_PCB, "protocol control blocks" }, /* XXX */ + { MT_RTABLE, "routing table entries" }, /* XXX */ + { MT_HTABLE, "IMP host table entries" }, /* XXX */ + { MT_ATABLE, "address resolution tables" }, + { MT_FTABLE, "fragment reassembly queue headers" }, /* XXX */ + { MT_SONAME, "socket names and addresses" }, + { MT_SOOPTS, "socket options" }, + { MT_RIGHTS, "access rights" }, + { MT_IFADDR, "interface addresses" }, /* XXX */ + { MSG_DATA, "Appletalk data blocks"}, + { MSG_PROTO, "Appletalk internal msgs"}, + { MSG_IOCTL, "Appletalk ioctl requests"}, + { MSG_ERROR, "Appletalk error indicators"}, + { MSG_HANGUP, "Appletalk termination requests"}, + { MSG_IOCACK, "Appletalk ioctl acks"}, + { MSG_IOCNAK, "Appletalk ioctl failure indicators"}, + { MSG_CTL, "Appletalk control msgs"}, + { 0, 0 } +}; + +int nmbtypes = sizeof(mbstat.m_mtypes) / sizeof(short); +bool seen[256]; /* "have we seen this type yet?" */ + +/* + * Print mbuf statistics. + */ +void +mbpr(mbaddr) + u_long mbaddr; +{ + register int totmem, totfree, totmbufs; + register int i; + register struct mbtypes *mp; + + if (nmbtypes != 256) { + fprintf(stderr, + "netstat: unexpected change to mbstat; check source\n"); + return; + } + if (mbaddr == 0) { + fprintf(stderr, "netstat: mbstat: symbol not in namelist\n"); + return; + } + if (kread(mbaddr, (char *)&mbstat, sizeof (mbstat))) + return; + + totmbufs = 0; + for (mp = mbtypes; mp->mt_name; mp++) + totmbufs += mbstat.m_mtypes[mp->mt_type]; + printf("%u mbufs in use:\n", totmbufs); + for (mp = mbtypes; mp->mt_name; mp++) + if (mbstat.m_mtypes[mp->mt_type]) { + seen[mp->mt_type] = YES; + printf("\t%u mbufs allocated to %s\n", + mbstat.m_mtypes[mp->mt_type], mp->mt_name); + } + seen[MT_FREE] = YES; + for (i = 0; i < nmbtypes; i++) + if (!seen[i] && mbstat.m_mtypes[i]) { + printf("\t%u mbufs allocated to \n", + mbstat.m_mtypes[i], i); + } + printf("%u/%u mbuf clusters in use\n", + (unsigned int)(mbstat.m_clusters - mbstat.m_clfree), + (unsigned int)mbstat.m_clusters); + totmem = totmbufs * MSIZE + mbstat.m_clusters * MCLBYTES; + totfree = mbstat.m_clfree * MCLBYTES; + printf("%u Kbytes allocated to network (%d%% in use)\n", + totmem / 1024, (totmem - totfree) * 100 / totmem); + printf("%u requests for memory denied\n", + (unsigned int)mbstat.m_drops); + printf("%u requests for memory delayed\n", (unsigned int)mbstat.m_wait); + printf("%u calls to protocol drain routines\n", + (unsigned int)mbstat.m_drain); +} diff --git a/netstat.tproj/mroute.c b/netstat.tproj/mroute.c new file mode 100644 index 0000000..03e47cc --- /dev/null +++ b/netstat.tproj/mroute.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989 Stephen Deering + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Stephen Deering of Stanford University. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)mroute.c 8.2 (Berkeley) 4/28/95 + */ + +/* + * Print DVMRP multicast routing structures and statistics. + * + * MROUTING 1.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include "netstat.h" + +void +mroutepr(mfcaddr, vifaddr) + u_long mfcaddr, vifaddr; +{ + u_int mrtproto; + struct mfc *mfctable[MFCTBLSIZ]; + struct vif viftable[MAXVIFS]; + struct mfc mfc, *m; + register struct vif *v; + register vifi_t vifi; + register int i; + register int banner_printed; + register int saved_nflag; + vifi_t maxvif = 0; + + if (mfcaddr == 0 || vifaddr == 0) { + printf("No multicast routing compiled into this system.\n"); + return; + } + + saved_nflag = nflag; + nflag = 1; + + kread(vifaddr, (char *)&viftable, sizeof(viftable)); + banner_printed = 0; + for (vifi = 0, v = viftable; vifi < MAXVIFS; ++vifi, ++v) { + if (v->v_lcl_addr.s_addr == 0) + continue; + + maxvif = vifi; + if (!banner_printed) { + printf("\nVirtual Interface Table\n" + " Vif Thresh Rate Local-Address " + "Remote-Address Pkts-In Pkts-Out\n"); + banner_printed = 1; + } + + printf(" %2u %6u %4d %-15.15s", + /* opposite math of add_vif() */ + vifi, v->v_threshold, v->v_rate_limit * 1000 / 1024, + routename(v->v_lcl_addr.s_addr)); + printf(" %-15.15s", (v->v_flags & VIFF_TUNNEL) ? + routename(v->v_rmt_addr.s_addr) : ""); + + printf(" %9lu %9lu\n", v->v_pkt_in, v->v_pkt_out); + } + if (!banner_printed) + printf("\nVirtual Interface Table is empty\n"); + + kread(mfcaddr, (char *)&mfctable, sizeof(mfctable)); + banner_printed = 0; + for (i = 0; i < MFCTBLSIZ; ++i) { + m = mfctable[i]; + while(m) { + kread((u_long)m, (char *)&mfc, sizeof mfc); + + if (!banner_printed) { + printf("\nMulticast Forwarding Cache\n" + " Origin Group " + " Packets In-Vif Out-Vifs:Ttls\n"); + banner_printed = 1; + } + + printf(" %-15.15s", routename(mfc.mfc_origin.s_addr)); + printf(" %-15.15s", routename(mfc.mfc_mcastgrp.s_addr)); + printf(" %9lu", mfc.mfc_pkt_cnt); + printf(" %3d ", mfc.mfc_parent); + for (vifi = 0; vifi <= maxvif; vifi++) { + if (mfc.mfc_ttls[vifi] > 0) + printf(" %u:%u", vifi, + mfc.mfc_ttls[vifi]); + } + printf("\n"); + m = mfc.mfc_next; + } + } + if (!banner_printed) + printf("\nMulticast Routing Table is empty\n"); + + printf("\n"); + nflag = saved_nflag; +} + + +void +mrt_stats(mstaddr) + u_long mstaddr; +{ + struct mrtstat mrtstat; + + if (mstaddr == 0) { + printf("No multicast routing compiled into this system.\n"); + return; + } + + kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat)); + printf("multicast forwarding:\n"); + printf(" %10lu multicast forwarding cache lookup%s\n", + mrtstat.mrts_mfc_lookups, plural(mrtstat.mrts_mfc_lookups)); + printf(" %10lu multicast forwarding cache miss%s\n", + mrtstat.mrts_mfc_misses, plurales(mrtstat.mrts_mfc_misses)); + printf(" %10lu upcall%s to mrouted\n", + mrtstat.mrts_upcalls, plural(mrtstat.mrts_upcalls)); + printf(" %10lu upcall queue overflow%s\n", + mrtstat.mrts_upq_ovflw, plural(mrtstat.mrts_upq_ovflw)); + printf(" %10lu upcall%s dropped due to full socket buffer\n", + mrtstat.mrts_upq_sockfull, plural(mrtstat.mrts_upq_sockfull)); + printf(" %10lu cache cleanup%s\n", + mrtstat.mrts_cache_cleanups, plural(mrtstat.mrts_cache_cleanups)); + printf(" %10lu datagram%s with no route for origin\n", + mrtstat.mrts_no_route, plural(mrtstat.mrts_no_route)); + printf(" %10lu datagram%s arrived with bad tunneling\n", + mrtstat.mrts_bad_tunnel, plural(mrtstat.mrts_bad_tunnel)); + printf(" %10lu datagram%s could not be tunneled\n", + mrtstat.mrts_cant_tunnel, plural(mrtstat.mrts_cant_tunnel)); + printf(" %10lu datagram%s arrived on wrong interface\n", + mrtstat.mrts_wrong_if, plural(mrtstat.mrts_wrong_if)); + printf(" %10lu datagram%s selectively dropped\n", + mrtstat.mrts_drop_sel, plural(mrtstat.mrts_drop_sel)); + printf(" %10lu datagram%s dropped due to queue overflow\n", + mrtstat.mrts_q_overflow, plural(mrtstat.mrts_q_overflow)); + printf(" %10lu datagram%s dropped for being too large\n", + mrtstat.mrts_pkt2large, plural(mrtstat.mrts_pkt2large)); +} diff --git a/netstat.tproj/netstat.1 b/netstat.tproj/netstat.1 new file mode 100644 index 0000000..fc0d303 --- /dev/null +++ b/netstat.tproj/netstat.1 @@ -0,0 +1,289 @@ +.\" Copyright (c) 1983, 1990, 1992, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)netstat.1 8.8 (Berkeley) 4/18/94 +.\" +.Dd April 18, 1994 +.Dt NETSTAT 1 +.Os BSD 4.2 +.Sh NAME +.Nm netstat +.Nd show network status +.Sh SYNOPSIS +.Nm netstat +.Op Fl Aan +.Op Fl f Ar address_family +.Op Fl M Ar core +.Op Fl N Ar system +.Nm netstat +.Op Fl dghimnrs +.Op Fl f Ar address_family +.Op Fl M Ar core +.Op Fl N Ar system +.Nm netstat +.Op Fl dn +.Op Fl I Ar interface +.Op Fl M Ar core +.Op Fl N Ar system +.Op Fl w Ar wait +.Nm netstat +.Op Fl p Ar protocol +.Op Fl M Ar core +.Op Fl N Ar system +.Sh DESCRIPTION +The +.Nm netstat +command symbolically displays the contents of various network-related +data structures. +There are a number of output formats, +depending on the options for the information presented. +The first form of the command displays a list of active sockets for +each protocol. +The second form presents the contents of one of the other network +data structures according to the option selected. +Using the third form, with a +.Ar wait +interval specified, +.Nm netstat +will continuously display the information regarding packet +traffic on the configured network interfaces. +The fourth form displays statistics about the named protocol. +.Pp +The options have the following meaning: +.Bl -tag -width flag +.It Fl A +With the default display, +show the address of any protocol control blocks associated with sockets; used +for debugging. +.It Fl a +With the default display, +show the state of all sockets; normally sockets used by +server processes are not shown. +.It Fl d +With either interface display (option +.Fl i +or an interval, as described below), +show the number of dropped packets. +.It Fl f Ar address_family +Limit statistics or address control block reports to those +of the specified +.Ar address family . +The following address families +are recognized: +.Ar inet , +for +.Dv AF_INET , +.Ar ns , +for +.Dv AF_NS , +.Ar iso , +for +.Dv AF_ISO , +and +.Ar unix , +for +.Dv AF_UNIX . +.It Fl g +Show information related to multicast (group address) routing. +By default, show the IP Multicast virtual-interface and routing tables. +If the +.Fl s +option is also present, show multicast routing statistics. +.It Fl h +Show the state of the +.Tn IMP +host table (obsolete). +.It Fl I Ar interface +Show information about the specified interface; +used with a +.Ar wait +interval as described below. +.It Fl i +Show the state of interfaces which have been auto-configured +(interfaces statically configured into a system, but not +located at boot time are not shown). +If the +.Fl a +options is also present, multicast addresses currently in use are shown +for each Ethernet interface and for each IP interface address. +Multicast addresses are shown on separate lines following the interface +address with which they are associated. +.It Fl M +Extract values associated with the name list from the specified core +instead of the default +.Pa /dev/kmem . +.It Fl m +Show statistics recorded by the memory management routines +(the network manages a private pool of memory buffers). +.It Fl N +Extract the name list from the specified system instead of the default +.Pa /vmunix . +.It Fl n +Show network addresses as numbers (normally +.Nm netstat +interprets addresses and attempts to display them +symbolically). +This option may be used with any of the display formats. +.It Fl p Ar protocol +Show statistics about +.Ar protocol , +which is either a well-known name for a protocol or an alias for it. Some +protocol names and aliases are listed in the file +.Pa /etc/protocols . +A null response typically means that there are no interesting numbers to +report. +The program will complain if +.Ar protocol +is unknown or if there is no statistics routine for it. +.It Fl s +Show per-protocol statistics. +If this option is repeated, counters with a value of zero are suppressed. +.It Fl r +Show the routing tables. +When +.Fl s +is also present, show routing statistics instead. +.It Fl w Ar wait +Show network interface statistics at intervals of +.Ar wait +seconds. +.El +.Pp +The default display, for active sockets, shows the local +and remote addresses, send and receive queue sizes (in bytes), protocol, +and the internal state of the protocol. +Address formats are of the form ``host.port'' or ``network.port'' +if a socket's address specifies a network but no specific host address. +When known the host and network addresses are displayed symbolically +according to the data bases +.Pa /etc/hosts +and +.Pa /etc/networks , +respectively. If a symbolic name for an address is unknown, or if +the +.Fl n +option is specified, the address is printed numerically, according +to the address family. +For more information regarding +the Internet ``dot format,'' +refer to +.Xr inet 3 ) . +Unspecified, +or ``wildcard'', addresses and ports appear as ``*''. +.Pp +The interface display provides a table of cumulative +statistics regarding packets transferred, errors, and collisions. +The network addresses of the interface +and the maximum transmission unit (``mtu'') are also displayed. +.Pp +The routing table display indicates the available routes and +their status. Each route consists of a destination host or network +and a gateway to use in forwarding packets. The flags field shows +a collection of information about the route stored as +binary choices. The individual flags are discussed in more +detail in the +.Xr route 8 +and +.Xr route 4 +manual pages. +The mapping between letters and flags is: +.Bl -column XXXX RTF_BLACKHOLE +1 RTF_PROTO2 Protocol specific routing flag #1 +2 RTF_PROTO1 Protocol specific routing flag #2 +B RTF_BLACKHOLE Just discard pkts (during updates) +C RTF_CLONING Generate new routes on use +D RTF_DYNAMIC Created dynamically (by redirect) +G RTF_GATEWAY Destination requires forwarding by intermediary +H RTF_HOST Host entry (net otherwise) +L RTF_LLINFO Valid protocol to link address translation. +M RTF_MODIFIED Modified dynamically (by redirect) +R RTF_REJECT Host or net unreachable +S RTF_STATIC Manually added +U RTF_UP Route usable +X RTF_XRESOLVE External daemon translates proto to link address +.El +.Pp +Direct routes are created for each +interface attached to the local host; +the gateway field for such entries shows the address of the outgoing interface. +The refcnt field gives the +current number of active uses of the route. Connection oriented +protocols normally hold on to a single route for the duration of +a connection while connectionless protocols obtain a route while sending +to the same destination. +The use field provides a count of the number of packets +sent using that route. The interface entry indicates the network +interface utilized for the route. +.Pp +When +.Nm netstat +is invoked with the +.Fl w +option and a +.Ar wait +interval argument, it displays a running count of statistics related to +network interfaces. +An obsolescent version of this option used a numeric parameter +with no option, and is currently supported for backward compatibility. +This display consists of a column for the primary interface (the first +interface found during autoconfiguration) and a column summarizing +information for all interfaces. +The primary interface may be replaced with another interface with the +.Fl I +option. +The first line of each screen of information contains a summary since the +system was last rebooted. Subsequent lines of output show values +accumulated over the preceding interval. +.Sh SEE ALSO +.Xr iostat 1 , +.Xr nfsstat 1 , +.Xr ps 1 , +.Xr vmstat 1 , +.Xr hosts 5 , +.Xr networks 5 , +.Xr protocols 5 , +.Xr services 5 , +.Xr trpt 8 , +.Xr trsp 8 +.Sh HISTORY +The +.Nm netstat +command appeared in +.Bx 4.2 . +.\" .Sh FILES +.\" .Bl -tag -width /dev/kmem -compact +.\" .It Pa /vmunix +.\" default kernel namelist +.\" .It Pa /dev/kmem +.\" default memory file +.\" .El +.Sh BUGS +The notion of errors is ill-defined. diff --git a/netstat.tproj/netstat.h b/netstat.tproj/netstat.h new file mode 100644 index 0000000..8a70629 --- /dev/null +++ b/netstat.tproj/netstat.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 + * Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)netstat.h 8.2 (Berkeley) 1/4/94 + */ + +#include +#include + +#ifndef EXTERN +#define EXTERN extern +#endif +EXTERN int Aflag; /* show addresses of protocol control block */ +EXTERN int aflag; /* show all sockets (including servers) */ +EXTERN int bflag; /* show i/f total bytes in/out */ +EXTERN int dflag; /* show i/f dropped packets */ +EXTERN int gflag; /* show group (multicast) routing or stats */ +EXTERN int iflag; /* show static interfaces */ +EXTERN int mflag; /* show memory stats */ +EXTERN int nflag; /* show addresses numerically */ +EXTERN int pflag; /* show given protocol */ +EXTERN int rflag; /* show routing tables (or routing stats) */ +EXTERN int sflag; /* show protocol statistics */ +EXTERN int tflag; /* show i/f watchdog timers */ + +EXTERN int interval; /* repeat interval for i/f stats */ + +EXTERN char *interface; /* desired i/f for stats, or NULL for all i/fs */ +EXTERN int unit; /* unit number for above */ + +EXTERN int af; /* address family */ + +int kread __P((u_long addr, char *buf, int size)); +char *plural __P((int)); +char *plurales __P((int)); +void trimdomain __P((char *)); + +void protopr __P((u_long, char *)); +void tcp_stats __P((u_long, char *)); +void udp_stats __P((u_long, char *)); +void ip_stats __P((u_long, char *)); +void icmp_stats __P((u_long, char *)); +void igmp_stats __P((u_long, char *)); +void protopr __P((u_long, char *)); + +void mbpr __P((u_long)); + +void hostpr __P((u_long, u_long)); +void impstats __P((u_long, u_long)); + +void intpr __P((int, u_long)); + +void pr_rthdr __P(()); +void pr_family __P((int)); +void rt_stats __P((u_long)); +char *ipx_pnet __P((struct sockaddr *)); +char *ipx_phost __P((struct sockaddr *)); +char *ns_phost __P((struct sockaddr *)); +void upHex __P((char *)); + +char *routename __P((u_long)); +char *netname __P((u_long, u_long)); +char *atalk_print __P((struct sockaddr *, int)); +char *atalk_print2 __P((struct sockaddr *, struct sockaddr *, int)); +char *ipx_print __P((struct sockaddr *)); +char *ns_print __P((struct sockaddr *)); +void routepr __P((u_long)); + +void ipxprotopr __P((u_long, char *)); +void spx_stats __P((u_long, char *)); +void ipx_stats __P((u_long, char *)); +void ipxerr_stats __P((u_long, char *)); + +void nsprotopr __P((u_long, char *)); +void spp_stats __P((u_long, char *)); +void idp_stats __P((u_long, char *)); +void nserr_stats __P((u_long, char *)); + +void atalkprotopr __P((u_long, char *)); +void ddp_stats __P((u_long, char *)); + +void intpr __P((int, u_long)); + +void unixpr __P((void)); + +void esis_stats __P((u_long, char *)); +void clnp_stats __P((u_long, char *)); +void cltp_stats __P((u_long, char *)); +void iso_protopr __P((u_long, char *)); +void iso_protopr1 __P((u_long, int)); +void tp_protopr __P((u_long, char *)); +void tp_inproto __P((u_long)); +void tp_stats __P((caddr_t, caddr_t)); + +void mroutepr __P((u_long, u_long)); +void mrt_stats __P((u_long)); + diff --git a/netstat.tproj/route.c b/netstat.tproj/route.c new file mode 100644 index 0000000..84b945a --- /dev/null +++ b/netstat.tproj/route.c @@ -0,0 +1,918 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95"; +#endif +static const char rcsid[] = + "$Id: route.c,v 1.1.1.2 2000/01/11 01:48:53 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef IPX +#include +#include +#endif + +#ifdef NS +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "netstat.h" + +#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d))) + +/* + * Definitions for showing gateway flags. + */ +struct bits { + u_long b_mask; + char b_val; +} bits[] = { + { RTF_UP, 'U' }, + { RTF_GATEWAY, 'G' }, + { RTF_HOST, 'H' }, + { RTF_REJECT, 'R' }, + { RTF_DYNAMIC, 'D' }, + { RTF_MODIFIED, 'M' }, + { RTF_DONE, 'd' }, /* Completed -- for routing messages only */ + { RTF_CLONING, 'C' }, + { RTF_XRESOLVE, 'X' }, + { RTF_LLINFO, 'L' }, + { RTF_STATIC, 'S' }, + { RTF_PROTO1, '1' }, + { RTF_PROTO2, '2' }, + { RTF_WASCLONED,'W' }, + { RTF_PRCLONING,'c' }, + { RTF_PROTO3, '3' }, + { RTF_BLACKHOLE,'B' }, + { RTF_BROADCAST,'b' }, + { 0 } +}; + +typedef union { + long dummy; /* Helps align structure. */ + struct sockaddr u_sa; + u_short u_data[128]; +} sa_u; + +static sa_u pt_u; + +int do_rtent = 0; +struct rtentry rtentry; +struct radix_node rnode; +struct radix_mask rmask; +struct radix_node_head *rt_tables[AF_MAX+1]; + +int NewTree = 0; + +static struct sockaddr *kgetsa __P((struct sockaddr *)); +static void p_tree __P((struct radix_node *)); +static void p_rtnode __P((void)); +static void ntreestuff __P((void)); +static void np_rtentry __P((struct rt_msghdr *)); +static void p_sockaddr __P((struct sockaddr *, struct sockaddr *, int, int)); +static void p_flags __P((int, char *)); +static void p_rtentry __P((struct rtentry *)); +static u_long forgemask __P((u_long)); +static void domask __P((char *, u_long, u_long)); + +/* + * Print routing tables. + */ +void +routepr(rtree) + u_long rtree; +{ + struct radix_node_head *rnh, head; + int i; + + printf("Routing tables\n"); + + if (Aflag == 0 && NewTree) + ntreestuff(); + else { + if (rtree == 0) { + printf("rt_tables: symbol not in namelist\n"); + return; + } + + kget(rtree, rt_tables); + for (i = 0; i <= AF_MAX; i++) { + if ((rnh = rt_tables[i]) == 0) + continue; + kget(rnh, head); + if (i == AF_UNSPEC) { + if (Aflag && af == 0) { + printf("Netmasks:\n"); + p_tree(head.rnh_treetop); + } + } else if (af == AF_UNSPEC || af == i) { + pr_family(i); + do_rtent = 1; + pr_rthdr(); + p_tree(head.rnh_treetop); + } + } + } +} + +/* + * Print address family header before a section of the routing table. + */ +void +pr_family(af) + int af; +{ + char *afname; + + switch (af) { + case AF_INET: + afname = "Internet"; + break; + +#ifdef IPX + case AF_IPX: + afname = "IPX"; + break; +#endif + +#ifdef NS + case AF_NS: + afname = "XNS"; + break; +#endif + case AF_ISO: + afname = "ISO"; + break; + case AF_APPLETALK: + afname = "AppleTalk"; + break; + case AF_CCITT: + afname = "X.25"; + break; + default: + afname = NULL; + break; + } + if (afname) + printf("\n%s:\n", afname); + else + printf("\nProtocol Family %d:\n", af); +} + +/* column widths; each followed by one space */ +#define WID_DST 18 /* width of destination column */ +#define WID_GW 18 /* width of gateway column */ + +/* + * Print header for routing table columns. + */ +void +pr_rthdr() +{ + if (Aflag) + printf("%-8.8s ","Address"); + printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %8.8s %6s\n", + WID_DST, WID_DST, "Destination", + WID_GW, WID_GW, "Gateway", + "Flags", "Refs", "Use", "Netif", "Expire"); +} + +static struct sockaddr * +kgetsa(dst) + register struct sockaddr *dst; +{ + + kget(dst, pt_u.u_sa); + if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa)) + kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len); + return (&pt_u.u_sa); +} + +static void +p_tree(rn) + struct radix_node *rn; +{ + +again: + kget(rn, rnode); + if (rnode.rn_b < 0) { + if (Aflag) + printf("%-8.8lx ", (u_long)rn); + if (rnode.rn_flags & RNF_ROOT) { + if (Aflag) + printf("(root node)%s", + rnode.rn_dupedkey ? " =>\n" : "\n"); + } else if (do_rtent) { + kget(rn, rtentry); + p_rtentry(&rtentry); + if (Aflag) + p_rtnode(); + } else { + p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key), + NULL, 0, 44); + putchar('\n'); + } + if ((rn = rnode.rn_dupedkey)) + goto again; + } else { + if (Aflag && do_rtent) { + printf("%-8.8lx ", (u_long)rn); + p_rtnode(); + } + rn = rnode.rn_r; + p_tree(rnode.rn_l); + p_tree(rn); + } +} + +char nbuf[20]; + +static void +p_rtnode() +{ + struct radix_mask *rm = rnode.rn_mklist; + + if (rnode.rn_b < 0) { + if (rnode.rn_mask) { + printf("\t mask "); + p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask), + NULL, 0, -1); + } else if (rm == 0) + return; + } else { + sprintf(nbuf, "(%d)", rnode.rn_b); + printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_l, (u_long)rnode.rn_r); + } + while (rm) { + kget(rm, rmask); + sprintf(nbuf, " %d refs, ", rmask.rm_refs); + printf(" mk = %8.8lx {(%d),%s", + (u_long)rm, -1 - rmask.rm_b, rmask.rm_refs ? nbuf : " "); + if (rmask.rm_flags & RNF_NORMAL) { + struct radix_node rnode_aux; + printf(" , "); + kget(rmask.rm_leaf, rnode_aux); + p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask), + NULL, 0, -1); + } else + p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask), + NULL, 0, -1); + putchar('}'); + if ((rm = rmask.rm_mklist)) + printf(" ->"); + } + putchar('\n'); +} + +static void +ntreestuff() +{ + size_t needed; + int mib[6]; + char *buf, *next, *lim; + register struct rt_msghdr *rtm; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_DUMP; + mib[5] = 0; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { + err(1, "sysctl: net.route.0.0.dump estimate"); + } + + if ((buf = malloc(needed)) == 0) { + err(2, "malloc(%lu)", (unsigned long)needed); + } + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { + err(1, "sysctl: net.route.0.0.dump"); + } + lim = buf + needed; + for (next = buf; next < lim; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)next; + np_rtentry(rtm); + } +} + +static void +np_rtentry(rtm) + register struct rt_msghdr *rtm; +{ + register struct sockaddr *sa = (struct sockaddr *)(rtm + 1); +#ifdef notdef + static int masks_done, banner_printed; +#endif + static int old_af; + int af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST; + +#ifdef notdef + /* for the moment, netmasks are skipped over */ + if (!banner_printed) { + printf("Netmasks:\n"); + banner_printed = 1; + } + if (masks_done == 0) { + if (rtm->rtm_addrs != RTA_DST ) { + masks_done = 1; + af = sa->sa_family; + } + } else +#endif + af = sa->sa_family; + if (af != old_af) { + pr_family(af); + old_af = af; + } + if (rtm->rtm_addrs == RTA_DST) + p_sockaddr(sa, NULL, 0, 36); + else { + p_sockaddr(sa, NULL, rtm->rtm_flags, 16); + if (sa->sa_len == 0) + sa->sa_len = sizeof(long); + sa = (struct sockaddr *)(sa->sa_len + (char *)sa); + p_sockaddr(sa, NULL, 0, 18); + } + p_flags(rtm->rtm_flags & interesting, "%-6.6s "); + putchar('\n'); +} + +static void +p_sockaddr(sa, mask, flags, width) + struct sockaddr *sa, *mask; + int flags, width; +{ + char workbuf[128], *cplim; + register char *cp = workbuf; + + switch(sa->sa_family) { + case AF_INET: + { + register struct sockaddr_in *sin = (struct sockaddr_in *)sa; + + if (sin->sin_addr.s_addr == INADDR_ANY) + cp = "default"; + else if (flags & RTF_HOST) + cp = routename(sin->sin_addr.s_addr); + else if (mask) + cp = netname(sin->sin_addr.s_addr, + ntohl(((struct sockaddr_in *)mask) + ->sin_addr.s_addr)); + else + cp = netname(sin->sin_addr.s_addr, 0L); + break; + } +#ifdef IPX + case AF_IPX: + { + struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; + if (ipx_nullnet(satoipx_addr(work))) + cp = "default"; + else + cp = ipx_print(sa); + break; + } +#endif + +#if 0 + case AF_APPLETALK: + { + if (!(flags & RTF_HOST) && mask) + cp = atalk_print2(sa,mask,9); + else + cp = atalk_print(sa,11); + break; + } +#endif + +#ifdef NS + case AF_NS: + cp = ns_print(sa); + break; +#endif + + case AF_LINK: + { + register struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa; + + if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && + sdl->sdl_slen == 0) + (void) sprintf(workbuf, "link#%d", sdl->sdl_index); + else + switch (sdl->sdl_type) { + + case IFT_ETHER: + { + register int i; + register u_char *lla = (u_char *)sdl->sdl_data + + sdl->sdl_nlen; + + cplim = ""; + for (i = 0; i < sdl->sdl_alen; i++, lla++) { + cp += sprintf(cp, "%s%x", cplim, *lla); + cplim = ":"; + } + cp = workbuf; + break; + } + + default: + cp = link_ntoa(sdl); + break; + } + break; + } + + default: + { + register u_char *s = (u_char *)sa->sa_data, *slim; + + slim = sa->sa_len + (u_char *) sa; + cplim = cp + sizeof(workbuf) - 6; + cp += sprintf(cp, "(%d)", sa->sa_family); + while (s < slim && cp < cplim) { + cp += sprintf(cp, " %02x", *s++); + if (s < slim) + cp += sprintf(cp, "%02x", *s++); + } + cp = workbuf; + } + } + if (width < 0 ) + printf("%s ", cp); + else { + if (nflag) + printf("%-*s ", width, cp); + else + printf("%-*.*s ", width, width, cp); + } +} + +static void +p_flags(f, format) + register int f; + char *format; +{ + char name[33], *flags; + register struct bits *p = bits; + + for (flags = name; p->b_mask; p++) + if (p->b_mask & f) + *flags++ = p->b_val; + *flags = '\0'; + printf(format, name); +} + +static void +p_rtentry(rt) + register struct rtentry *rt; +{ + static struct ifnet ifnet, *lastif; + static char name[16]; + static char prettyname[9]; + struct sockaddr *sa; + sa_u addr, mask; + + /* + * Don't print protocol-cloned routes unless -a. + */ + if (rt->rt_parent && !aflag) + return; + + bzero(&addr, sizeof(addr)); + if ((sa = kgetsa(rt_key(rt)))) + bcopy(sa, &addr, sa->sa_len); + bzero(&mask, sizeof(mask)); + if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt)))) + bcopy(sa, &mask, sa->sa_len); + p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, WID_DST); + p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW); + p_flags(rt->rt_flags, "%-6.6s "); + printf("%6d %8ld ", rt->rt_refcnt, rt->rt_use); + if (rt->rt_ifp) { + if (rt->rt_ifp != lastif) { + kget(rt->rt_ifp, ifnet); + kread((u_long)ifnet.if_name, name, 16); + lastif = rt->rt_ifp; + snprintf(prettyname, sizeof prettyname, + "%.6s%d", name, ifnet.if_unit); + } + printf("%8.8s", prettyname); + if (rt->rt_rmx.rmx_expire) { + time_t expire_time; + + if ((expire_time = + rt->rt_rmx.rmx_expire - time((time_t *)0)) > 0) + printf(" %6d%s", (int)expire_time, + rt->rt_nodes[0].rn_dupedkey ? " =>" : ""); + } else if (rt->rt_nodes[0].rn_dupedkey) { + printf(" =>"); + } + + } + putchar('\n'); +} + +char * +routename(in) + u_long in; +{ + register char *cp; + static char line[MAXHOSTNAMELEN + 1]; + struct hostent *hp; + + cp = 0; + if (!nflag) { + hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), + AF_INET); + if (hp) { + cp = hp->h_name; + trimdomain(cp); + } + } + if (cp) { + strncpy(line, cp, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; + } else { +#define C(x) ((x) & 0xff) + in = ntohl(in); + sprintf(line, "%lu.%lu.%lu.%lu", + C(in >> 24), C(in >> 16), C(in >> 8), C(in)); + } + return (line); +} + +static u_long +forgemask(a) + u_long a; +{ + u_long m; + + if (IN_CLASSA(a)) + m = IN_CLASSA_NET; + else if (IN_CLASSB(a)) + m = IN_CLASSB_NET; + else + m = IN_CLASSC_NET; + return (m); +} + +static void +domask(dst, addr, mask) + char *dst; + u_long addr, mask; +{ + register int b, i; + + if (!mask || (forgemask(addr) == mask)) { + *dst = '\0'; + return; + } + i = 0; + for (b = 0; b < 32; b++) + if (mask & (1 << b)) { + register int bb; + + i = b; + for (bb = b+1; bb < 32; bb++) + if (!(mask & (1 << bb))) { + i = -1; /* noncontig */ + break; + } + break; + } + if (i == -1) + sprintf(dst, "&0x%lx", mask); + else + sprintf(dst, "/%d", 32-i); +} + +/* + * Return the name of the network whose address is given. + * The address is assumed to be that of a net or subnet, not a host. + */ +char * +netname(in, mask) + u_long in, mask; +{ + char *cp = 0; + static char line[MAXHOSTNAMELEN + 1]; + struct netent *np = 0; + u_long net, omask, dmask; + register u_long i; + + i = ntohl(in); + omask = mask; + if (!nflag && i) { + dmask = forgemask(i); + net = i & dmask; + if (!(np = getnetbyaddr(i, AF_INET)) && net != i) + np = getnetbyaddr(net, AF_INET); + if (np) { + cp = np->n_name; + trimdomain(cp); + } + } + if (cp) + strncpy(line, cp, sizeof(line) - 1); + else if ((i & 0xffffff) == 0) + sprintf(line, "%lu", C(i >> 24)); + else if ((i & 0xffff) == 0) + sprintf(line, "%lu.%lu", C(i >> 24) , C(i >> 16)); + else if ((i & 0xff) == 0) + sprintf(line, "%lu.%lu.%lu", C(i >> 24), C(i >> 16), C(i >> 8)); + else + sprintf(line, "%lu.%lu.%lu.%lu", C(i >> 24), + C(i >> 16), C(i >> 8), C(i)); + domask(line+strlen(line), i, omask); + return (line); +} + +/* + * Print routing statistics + */ +void +rt_stats(off) + u_long off; +{ + struct rtstat rtstat; + + if (off == 0) { + printf("rtstat: symbol not in namelist\n"); + return; + } + kread(off, (char *)&rtstat, sizeof (rtstat)); + printf("routing:\n"); + printf("\t%u bad routing redirect%s\n", + rtstat.rts_badredirect, plural(rtstat.rts_badredirect)); + printf("\t%u dynamically created route%s\n", + rtstat.rts_dynamic, plural(rtstat.rts_dynamic)); + printf("\t%u new gateway%s due to redirects\n", + rtstat.rts_newgateway, plural(rtstat.rts_newgateway)); + printf("\t%u destination%s found unreachable\n", + rtstat.rts_unreach, plural(rtstat.rts_unreach)); + printf("\t%u use%s of a wildcard route\n", + rtstat.rts_wildcard, plural(rtstat.rts_wildcard)); +} + +#ifdef IPX + +char * +ipx_print(sa) + register struct sockaddr *sa; +{ + u_short port; + struct servent *sp = 0; + char *net = "", *host = ""; + register char *p; + register u_char *q; + struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr; + static char mybuf[50]; + char cport[10], chost[15], cnet[15]; + + port = ntohs(work.x_port); + + if (ipx_nullnet(work) && ipx_nullhost(work)) { + + if (port) { + if (sp) + sprintf(mybuf, "*.%s", sp->s_name); + else + sprintf(mybuf, "*.%x", port); + } else + sprintf(mybuf, "*.*"); + + return (mybuf); + } + + if (ipx_wildnet(work)) + net = "any"; + else if (ipx_nullnet(work)) + net = "*"; + else { + q = work.x_net.c_net; + sprintf(cnet, "%02x%02x%02x%02x", + q[0], q[1], q[2], q[3]); + for (p = cnet; *p == '0' && p < cnet + 8; p++) + continue; + net = p; + } + + if (ipx_wildhost(work)) + host = "any"; + else if (ipx_nullhost(work)) + host = "*"; + else { + q = work.x_host.c_host; + sprintf(chost, "%02x%02x%02x%02x%02x%02x", + q[0], q[1], q[2], q[3], q[4], q[5]); + for (p = chost; *p == '0' && p < chost + 12; p++) + continue; + host = p; + } + + if (port) { + if (strcmp(host, "*") == 0) + host = ""; + if (sp) + snprintf(cport, sizeof(cport), + "%s%s", *host ? "." : "", sp->s_name); + else + snprintf(cport, sizeof(cport), + "%s%x", *host ? "." : "", port); + } else + *cport = 0; + + snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport); + return(mybuf); +} + +char * +ipx_phost(sa) + struct sockaddr *sa; +{ + register struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa; + struct sockaddr_ipx work; + static union ipx_net ipx_zeronet; + char *p; + struct ipx_addr in; + + work = *sipx; + in = work.sipx_addr; + + work.sipx_addr.x_port = 0; + work.sipx_addr.x_net = ipx_zeronet; + p = ipx_print((struct sockaddr *)&work); + if (strncmp("*.", p, 2) == 0) p += 2; + + return(p); +} +#endif + +#ifdef NS +short ns_nullh[] = {0,0,0}; +short ns_bh[] = {-1,-1,-1}; + +char * +ns_print(sa) + register struct sockaddr *sa; +{ + register struct sockaddr_ns *sns = (struct sockaddr_ns*)sa; + struct ns_addr work; + union { union ns_net net_e; u_long long_e; } net; + u_short port; + static char mybuf[50], cport[10], chost[25]; + char *host = ""; + register char *p; register u_char *q; + + work = sns->sns_addr; + port = ntohs(work.x_port); + work.x_port = 0; + net.net_e = work.x_net; + if (ns_nullhost(work) && net.long_e == 0) { + if (port ) { + sprintf(mybuf, "*.%xH", port); + upHex(mybuf); + } else + sprintf(mybuf, "*.*"); + return (mybuf); + } + + if (bcmp(ns_bh, work.x_host.c_host, 6) == 0) { + host = "any"; + } else if (bcmp(ns_nullh, work.x_host.c_host, 6) == 0) { + host = "*"; + } else { + q = work.x_host.c_host; + sprintf(chost, "%02x%02x%02x%02x%02x%02xH", + q[0], q[1], q[2], q[3], q[4], q[5]); + for (p = chost; *p == '0' && p < chost + 12; p++) + continue; + host = p; + } + if (port) + sprintf(cport, ".%xH", htons(port)); + else + *cport = 0; + + sprintf(mybuf,"%xH.%s%s", ntohl(net.long_e), host, cport); + upHex(mybuf); + return(mybuf); +} + +char * +ns_phost(sa) + struct sockaddr *sa; +{ + register struct sockaddr_ns *sns = (struct sockaddr_ns *)sa; + struct sockaddr_ns work; + static union ns_net ns_zeronet; + char *p; + + work = *sns; + work.sns_addr.x_port = 0; + work.sns_addr.x_net = ns_zeronet; + + p = ns_print((struct sockaddr *)&work); + if (strncmp("0H.", p, 3) == 0) + p += 3; + return(p); +} +#endif + +void +upHex(p0) + char *p0; +{ + register char *p = p0; + + for (; *p; p++) + switch (*p) { + + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + *p += ('A' - 'a'); + break; + } +} diff --git a/netstat.tproj/tp_astring.c b/netstat.tproj/tp_astring.c new file mode 100644 index 0000000..af08ceb --- /dev/null +++ b/netstat.tproj/tp_astring.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tp_astring.c 8.1 (Berkeley) 6/10/93 + */ + +char *tp_sstring[] = { +"ST_ERROR(0x0)", +"TP_CLOSED(0x1)", +"TP_CRSENT(0x2)", +"TP_AKWAIT(0x3)", +"TP_OPEN(0x4)", +"TP_CLOSING(0x5)", +"TP_REFWAIT(0x6)", +"TP_LISTENING(0x7)", +"TP_CONFIRMING(0x8)", +}; + +char *tp_estring[] = { +"TM_inact(0x0)", +"TM_retrans(0x1)", +"TM_sendack(0x2)", +"TM_notused(0x3)", +"TM_reference(0x4)", +"TM_data_retrans(0x5)", +"ER_TPDU(0x6)", +"CR_TPDU(0x7)", +"DR_TPDU(0x8)", +"DC_TPDU(0x9)", +"CC_TPDU(0xa)", +"AK_TPDU(0xb)", +"DT_TPDU(0xc)", +"XPD_TPDU(0xd)", +"XAK_TPDU(0xe)", +"T_CONN_req(0xf)", +"T_DISC_req(0x10)", +"T_LISTEN_req(0x11)", +"T_DATA_req(0x12)", +"T_XPD_req(0x13)", +"T_USR_rcvd(0x14)", +"T_USR_Xrcvd(0x15)", +"T_DETACH(0x16)", +"T_NETRESET(0x17)", +"T_ACPT_req(0x18)", +}; diff --git a/netstat.tproj/unix.c b/netstat.tproj/unix.c new file mode 100644 index 0000000..c61c855 --- /dev/null +++ b/netstat.tproj/unix.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)unix.c 8.1 (Berkeley) 6/6/93"; +#endif +static const char rcsid[] = + "$Id: unix.c,v 1.1.1.2 2000/01/11 01:48:53 wsanchez Exp $"; +#endif /* not lint */ + +/* + * Display protocol blocks in the unix domain. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include "netstat.h" + +static void unixdomainpr __P((struct xunpcb *, struct xsocket *)); + +static const char *const socktype[] = + { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" }; + +void +unixpr() +{ + char *buf; + int type; + size_t len; + struct xsocket *so; + struct xunpgen *xug, *oxug; + struct xunpcb *xunp; + char mibvar[sizeof "net.local.seqpacket.pcblist"]; + + for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) { + sprintf(mibvar, "net.local.%s.pcblist", socktype[type]); + + len = 0; + if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { + if (errno != ENOENT) + warn("sysctl: %s", mibvar); + continue; + } + if ((buf = malloc(len)) == 0) { + warn("malloc %lu bytes", (u_long)len); + return; + } + if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { + warn("sysctl: %s", mibvar); + free(buf); + return; + } + + oxug = xug = (struct xunpgen *)buf; + for (xug = (struct xunpgen *)((char *)xug + xug->xug_len); + xug->xug_len > sizeof(struct xunpgen); + xug = (struct xunpgen *)((char *)xug + xug->xug_len)) { + xunp = (struct xunpcb *)xug; + so = &xunp->xu_socket; + + /* Ignore PCBs which were freed during copyout. */ + if (xunp->xu_unp.unp_gencnt > oxug->xug_gen) + continue; + unixdomainpr(xunp, so); + } + if (xug != oxug && xug->xug_gen != oxug->xug_gen) { + if (oxug->xug_count > xug->xug_count) { + printf("Some %s sockets may have been deleted.\n", + socktype[type]); + } else if (oxug->xug_count < xug->xug_count) { + printf("Some %s sockets may have been created.\n", + socktype[type]); + } else { + printf("Some %s sockets may have been created or deleted", + socktype[type]); + } + } + free(buf); + } +} + +static void +unixdomainpr(xunp, so) + struct xunpcb *xunp; + struct xsocket *so; +{ + struct unpcb *unp; + struct sockaddr_un *sa; + static int first = 1; + + unp = &xunp->xu_unp; + if (unp->unp_addr) + sa = &xunp->xu_addr; + else + sa = (struct sockaddr_un *)0; + + if (first) { + printf("Active LOCAL (UNIX) domain sockets\n"); + printf( +"%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n", + "Address", "Type", "Recv-Q", "Send-Q", + "Inode", "Conn", "Refs", "Nextref"); + first = 0; + } + printf("%8lx %-6.6s %6ld %6ld %8lx %8lx %8lx %8lx", + (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc, + so->so_snd.sb_cc, + (long)unp->unp_vnode, (long)unp->unp_conn, + (long)unp->unp_refs.lh_first, (long)unp->unp_reflink.le_next); + if (sa) + printf(" %.*s", + (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)), + sa->sun_path); + putchar('\n'); +} diff --git a/newclient.tproj/Makefile b/newclient.tproj/Makefile new file mode 100644 index 0000000..e822c95 --- /dev/null +++ b/newclient.tproj/Makefile @@ -0,0 +1,36 @@ +# +# Stubbed Legacy Makefile for the newclient script +# + +NAME = newclient + +OTHERSRCS = Makefile Makefile.preamble newclient.csh + +MAKEFILEDIR = $(MAKEFILEPATH)/project +MAKEFILE = common.make + +# INSTALL is already set to "install -S" +XINSTALL = install + +INSTALLDIR=/usr/sbin + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies + +all project $(NAME): + +install: + @dstdir=$(DSTROOT)`grep NEXTSTEP_INSTALLDIR PB.project | sed 's/.*= \(.*\);.*/\1/'`; \ + if [ ! -d $$dstdir ]; then \ + $(MKDIRS) $$dstdir; \ + fi; \ + $(RM) -f $$dstdir/$(NAME); \ + echo $(XINSTALL) -c -o $(INSTALL_AS_USER) -g $(INSTALL_AS_GROUP) \ + -m 555 newclient.csh $$dstdir/$(NAME); \ + $(XINSTALL) -c -o $(INSTALL_AS_USER) -g $(INSTALL_AS_GROUP) \ + -m 555 newclient.csh $$dstdir/$(NAME) diff --git a/newclient.tproj/Makefile.preamble b/newclient.tproj/Makefile.preamble new file mode 100644 index 0000000..fe326e5 --- /dev/null +++ b/newclient.tproj/Makefile.preamble @@ -0,0 +1 @@ +-include ../Makefile.include diff --git a/newclient.tproj/PB.project b/newclient.tproj/PB.project new file mode 100644 index 0000000..08d2bf1 --- /dev/null +++ b/newclient.tproj/PB.project @@ -0,0 +1,34 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (); + OTHER_SOURCES = (Makefile, Makefile.preamble, newclient.csh); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = newclient; + PROJECTTYPE = Legacy; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/newclient.tproj/newclient.csh b/newclient.tproj/newclient.csh new file mode 100644 index 0000000..af24796 --- /dev/null +++ b/newclient.tproj/newclient.csh @@ -0,0 +1,233 @@ +#! /bin/csh -f +## +# Copyright (c) 1999 Apple Computer, Inc. All rights reserved. +# +# @APPLE_LICENSE_HEADER_START@ +# +# "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights +# Reserved. This file contains Original Code and/or Modifications of +# Original Code as defined in and that are subject to the Apple Public +# Source License Version 1.0 (the 'License'). You may not use this file +# except in compliance with the License. Please obtain a copy of the +# License at http://www.apple.com/publicsource and read it before using +# this file. +# +# The Original Code and all software distributed under the License are +# distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the +# License for the specific language governing rights and limitations +# under the License." +# +# @APPLE_LICENSE_HEADER_END@ +## +# +# newclient +# +# NetBoot client building script. +# +# Copyright (c) 1988, NeXT, Inc. +# +# Usage: +# "newclient -p DISKTYPE TEMPLATE DEST" Standalone Private +# "newclient [-s SERVER] CLIENT-1 ... CLIENT-n" Clients +# + +# +# Constants +# +set path=(/bin /usr/bin /usr/ucb /usr/etc /etc) +set TESTDIR +set CLIENTDIR=${TESTDIR}/clients +set template=${TESTDIR}/usr/template/client +set HOSTFILE=${TESTDIR}/etc/hosts +set BOOTPTAB=${TESTDIR}/etc/bootptab + +# We are the default server +set server=`hostname` + +# Are we root? +if ( `whoami` != root ) then + echo "You must be root to run $0" + exit(1) +endif + +# Preliminary argument checkout +if ( $#argv < 1 ) then + goto usage +endif + +# Switches must be at argv[1] +foreach arg ( $argv[2-] ) + if ( x$arg =~ x-* ) then + goto usage + endif +end + +# Parse the switches +if ( $argv[1] == -p || $argv[1] == -P ) then + if ( $#argv != 4 ) then + goto usage + endif + set PrivateMode + set disktype=$argv[2] + set template=$argv[3] + set dest=$argv[4] + if ( $argv[1] == -P ) then + set swapsize=1b + else + set swapsize=16m + endif + + # Check that the disk type is valid + if ( ! -e $template/etc/fstab.$disktype ) then + echo "Unknown disk type" $disktype + exit(1) + endif +else if ( $argv[1] == -s ) then + if ( $#argv < 3 ) then + goto usage + endif + set server=$argv[2] + shift + shift +else if ( $argv[1] =~ -* ) then + goto usage +endif + +# Make sure we have a template to work with +if ( ! -d $template ) then + echo "New client template $template does not exist" + exit(1) +endif + +# Process the private partition if that is the mode we are in. +if ( $?PrivateMode ) then + if ( -e $dest ) then + echo "$dest already exists" + exit(1) + endif + + # Create the destination directory + echo -n "Creating ${dest}..." + mkdir $dest + chmod 775 $dest + chown root.staff $dest + if ( $status != 0 ) then + echo "failed" + exit(1) + endif + echo "[OK]" + + # Copy the template into it + echo -n "Copying ${template} into ${dest}..." + (cd $template; tar cf - .)|(cd $dest; tar xpBf -) + echo "[OK]" + + # Make the device files + echo -n "Making devices in ${dest}/dev..." + (cd ${dest}/dev; /usr/etc/MAKEDEV NeXT) + echo "[OK]" + + # Customize the fstab file + echo -n "Installing fstab.$disktype as ${dest}/etc/fstab..." + cp -p $dest/etc/fstab.${disktype} $dest/etc/fstab + if ( $status != 0 ) then + echo "failed" + exit(1) + endif + echo "[OK]" + + # Touch the first 16 Meg of the swapfile + echo -n "Preallocating swapfile blocks..." + (cd ${dest}/vm; /bin/rm -f swapfile; /usr/etc/mkfile $swapsize swapfile) + echo "[OK]" + + exit(0) +endif + +# +# If we get here, then we are building a list of clients +# + +echo $argv[*] +foreach client ( $argv[*] ) + if ( $server == localhost ) then + echo "This machine can't be a server until it is given a hostname" + exit(1) + endif + set dest=$CLIENTDIR/$client + + if (! -f /private/tftpboot/mach) then + echo Installing /private/tftpboot/mach + cp -p /mach /private/tftpboot/mach + endif + if (! -f /private/tftpboot/boot) then + echo Installing /private/tftpboot/boot + cp -p /usr/standalone/boot /private/tftpboot/boot + endif + + # Check for already existing client directory + if ( -e $dest ) then + echo $dest already exists + continue + endif + + # Create the destination directory + echo -n "Creating $dest..." + mkdir -p -m $dest + chown root:staff $dest + if ( $status != 0 ) then + echo "failed" + exit(1) + endif + echo "[OK]" + + # Copy the template into it. + echo -n "Copying $template into ${dest}..." + (cd $template; tar cf - .)|(cd $dest; tar xpBf -) + echo "[OK]" + + # Make the device files + echo -n "Making devices in ${dest}/dev..." + (cd $dest/dev; /usr/etc/MAKEDEV NeXT) + echo "[OK]" + + # Customize the fstab file + echo -n "Installing fstab.client as ${dest}/etc/fstab..." + cp -p $dest/etc/fstab.client $dest/etc/fstab + sed -e "s/SERVER/$server/g" -e "s/CLIENT/$client/g" $dest/etc/fstab.client > $dest/etc/fstab + if ( $status != 0 ) then + echo $failed + exit(1) + endif + echo "[OK]" + + # Set up a symbolic link to the kernel + + if (-f ${dest}/tftpboot/mach) then + echo -n "Removing ${dest}/tftpboot/mach " + rm ${dest}/tftpboot/mach + echo "[OK]" + endif + + echo -n "Linking /tftpboot/mach to /sdmach " + ln -s /sdmach ${dest}/tftpboot/mach + echo "[OK]" + + # Touch the first 16 Meg of the swapfile + echo -n "Creating swapfile..." + (cd ${dest}/vm; /bin/rm -f swapfile; /usr/etc/mkfile 8k swapfile) + echo "[OK]" + +end + +exit(0) + +usage: + echo "Usage: $0 -p DISKTYPE TEMPLATE DEST" + echo " $0 [-s SERVER] CLIENT CLIENT ..." + exit(1) + + diff --git a/nfsd.tproj/Makefile b/nfsd.tproj/Makefile new file mode 100644 index 0000000..a765f04 --- /dev/null +++ b/nfsd.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = nfsd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = nfsd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.dist nfsd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DNFS -DMACH_USER_API +WINDOWS_PB_CFLAGS = -DNFS -DMACH_USER_API +PDO_UNIX_PB_CFLAGS = -DNFS -DMACH_USER_API + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/nfsd.tproj/Makefile.dist b/nfsd.tproj/Makefile.dist new file mode 100644 index 0000000..35d0d0e --- /dev/null +++ b/nfsd.tproj/Makefile.dist @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= nfsd +CFLAGS+=-DNFS +MAN8= nfsd.0 +DPADD= ${LIBRPC} +LDADD= -lrpc + +.include diff --git a/nfsd.tproj/Makefile.preamble b/nfsd.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/nfsd.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/nfsd.tproj/PB.project b/nfsd.tproj/PB.project new file mode 100644 index 0000000..f314b1d --- /dev/null +++ b/nfsd.tproj/PB.project @@ -0,0 +1,32 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (nfsd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, nfsd.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = nfsd; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = nfsd; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = nfsd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = nfsd; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/nfsd.tproj/nfsd.8 b/nfsd.tproj/nfsd.8 new file mode 100644 index 0000000..e98aa13 --- /dev/null +++ b/nfsd.tproj/nfsd.8 @@ -0,0 +1,115 @@ +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)nfsd.8 8.4 (Berkeley) 3/29/95 +.\" +.Dd March 29, 1995 +.Dt NFSD 8 +.Os +.Sh NAME +.Nm nfsd +.Nd remote +.Tn NFS +server +.Sh SYNOPSIS +.Nm nfsd +.Op Fl rut +.Op Fl n Ar num_servers +.Sh DESCRIPTION +.Nm Nfsd +runs on a server machine to service +.Tn NFS +requests from client machines. +At least one +.Nm nfsd +must be running for a machine to operate as a server. +.Pp +Unless otherwise specified, four servers for +.Tn UDP +transport are started. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl r +Register the +.Tn NFS +service with +.Xr portmap 8 +without creating any servers. +This option can be used along with the +.Fl u +or +.Fl t +options to re-register NFS if the portmap server is restarted. +.It Fl n +Specifies how many servers to create. +.It Fl t +Serve +.Tn TCP NFS +clients. +.It Fl u +Serve +.Tn UDP NFS +clients. +.El +.Pp +For example, +.Dq Li "nfsd -u -t 6" +serves +.Tn UDP +and +.Tn TCP +transports using six daemons. +.Pp +A server should run enough daemons to handle +the maximum level of concurrency from its clients, +typically four to six. +.Pp +.Nm Nfsd +listens for service requests at the port indicated in the +.Tn NFS +server specification; see +.%T "Network File System Protocol Specification" , +RFC1094 and +.%T "NFS: Network File System Version 3 Protocol Specification" . +.Pp +The +.Nm nfsd +utility exits 0 on success, and >0 if an error occurs. +.Sh SEE ALSO +.Xr nfsstat 1 , +.Xr nfssvc 2 , +.Xr mountd 8 , +.Xr portmap 8 +.Sh HISTORY +The +.Nm nfsd +utility first appeared in 4.4BSD. diff --git a/nfsd.tproj/nfsd.c b/nfsd.tproj/nfsd.c new file mode 100644 index 0000000..1c5acec --- /dev/null +++ b/nfsd.tproj/nfsd.c @@ -0,0 +1,657 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef ISO +#include +#endif +#include +#include +#include + +#ifdef NFSKERB +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global defs */ +#ifdef DEBUG +#define syslog(e, s) fprintf(stderr,(s)) +int debug = 1; +#else +int debug = 0; +#endif + +struct nfsd_srvargs nsd; +char **Argv = NULL; /* pointer to argument vector */ +char *LastArg = NULL; /* end of argv */ + +#ifdef NFSKERB +char lnam[ANAME_SZ]; +KTEXT_ST kt; +AUTH_DAT kauth; +char inst[INST_SZ]; +struct nfsrpc_fullblock kin, kout; +struct nfsrpc_fullverf kverf; +NFSKERBKEY_T kivec; +struct timeval ktv; +NFSKERBKEYSCHED_T kerb_keysched; +#endif + +void nonfs __P((int)); +void reapchild __P((int)); +void setproctitle __P((char *)); +void usage __P((void)); + +/* + * Nfs server daemon mostly just a user context for nfssvc() + * + * 1 - do file descriptor and signal cleanup + * 2 - fork the nfsd(s) + * 3 - create server socket(s) + * 4 - register socket with portmap + * + * For connectionless protocols, just pass the socket into the kernel via. + * nfssvc(). + * For connection based sockets, loop doing accepts. When you get a new + * socket from accept, pass the msgsock into the kernel via. nfssvc(). + * The arguments are: + * -c - support iso cltp clients + * -r - reregister with portmapper + * -t - support tcp nfs clients + * -u - support udp nfs clients + * followed by "n" which is the number of nfsds' to fork off + */ +int +main(argc, argv, envp) + int argc; + char *argv[], *envp[]; +{ + extern int optind; + struct group *grp; + struct nfsd_args nfsdargs; + struct passwd *pwd; + struct ucred *cr; + struct sockaddr_in inetaddr, inetpeer; +#ifdef ISO + struct sockaddr_iso isoaddr, isopeer; +#endif + struct timeval ktv; + fd_set ready, sockbits; + int ch, cltpflag, connect_type_cnt, i, len, maxsock, msgsock; + int nfsdcnt, nfssvc_flag, on, reregister, sock, tcpflag, tcpsock; + int tp4cnt, tp4flag, tp4sock, tpipcnt, tpipflag, tpipsock, udpflag; + char *cp, **cpp; + + /* Save start and extent of argv for setproctitle. */ + Argv = argv; + if (envp == 0 || *envp == 0) + envp = argv; + while (*envp) + envp++; + LastArg = envp[-1] + strlen(envp[-1]); + +#define MAXNFSDCNT 20 +#define DEFNFSDCNT 4 + nfsdcnt = DEFNFSDCNT; + cltpflag = reregister = tcpflag = tp4cnt = tp4flag = tpipcnt = 0; + tpipflag = udpflag = 0; +#ifdef ISO +#define GETOPT "cn:rtu" +#define USAGE "[-crtu] [-n num_servers]" +#else +#define GETOPT "n:rtu" +#define USAGE "[-rtu] [-n num_servers]" +#endif + while ((ch = getopt(argc, argv, GETOPT)) != EOF) + switch (ch) { + case 'n': + nfsdcnt = atoi(optarg); + if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { + warnx("nfsd count %d; reset to %d", DEFNFSDCNT); + nfsdcnt = DEFNFSDCNT; + } + break; + case 'r': + reregister = 1; + break; + case 't': + tcpflag = 1; + break; + case 'u': + udpflag = 1; + break; +#ifdef ISO + case 'c': + cltpflag = 1; + break; +#ifdef notyet + case 'i': + tp4cnt = 1; + break; + case 'p': + tpipcnt = 1; + break; +#endif /* notyet */ +#endif /* ISO */ + default: + case '?': + usage(); + }; + argv += optind; + argc -= optind; + + /* + * XXX + * Backward compatibility, trailing number is the count of daemons. + */ + if (argc > 1) + usage(); + if (argc == 1) { + nfsdcnt = atoi(argv[0]); + if (nfsdcnt < 1 || nfsdcnt > MAXNFSDCNT) { + warnx("nfsd count %d; reset to %d", DEFNFSDCNT); + nfsdcnt = DEFNFSDCNT; + } + } + + if (debug == 0) { + daemon(0, 0); + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGSYS, nonfs); + (void)signal(SIGTERM, SIG_IGN); + } + (void)signal(SIGCHLD, reapchild); + + if (reregister) { + if (udpflag && + (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || + !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT))) + err(1, "can't register with portmap for UDP."); + if (tcpflag && + (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || + !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT))) + err(1, "can't register with portmap for TCP."); + exit(0); + } + openlog("nfsd:", LOG_PID, LOG_DAEMON); + + for (i = 0; i < nfsdcnt; i++) { + switch (fork()) { + case -1: + syslog(LOG_ERR, "fork: %m"); + exit (1); + case 0: + break; + default: + continue; + } + + setproctitle("server"); + nfssvc_flag = NFSSVC_NFSD; + nsd.nsd_nfsd = NULL; +#ifdef NFSKERB + if (sizeof (struct nfsrpc_fullverf) != RPCX_FULLVERF || + sizeof (struct nfsrpc_fullblock) != RPCX_FULLBLOCK) + syslog(LOG_ERR, "Yikes NFSKERB structs not packed!"); + nsd.nsd_authstr = (u_char *)&kt; + nsd.nsd_authlen = sizeof (kt); + nsd.nsd_verfstr = (u_char *)&kverf; + nsd.nsd_verflen = sizeof (kverf); +#endif + while (nfssvc(nfssvc_flag, &nsd) < 0) { + if (errno != ENEEDAUTH) { + syslog(LOG_ERR, "nfssvc: %m"); + exit(1); + } + nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHINFAIL; +#ifdef NFSKERB + /* + * Get the Kerberos ticket out of the authenticator + * verify it and convert the principal name to a user + * name. The user name is then converted to a set of + * user credentials via the password and group file. + * Finally, decrypt the timestamp and validate it. + * For more info see the IETF Draft "Authentication + * in ONC RPC". + */ + kt.length = ntohl(kt.length); + if (gettimeofday(&ktv, (struct timezone *)0) == 0 && + kt.length > 0 && kt.length <= + (RPCAUTH_MAXSIZ - 3 * NFSX_UNSIGNED)) { + kin.w1 = NFS_KERBW1(kt); + kt.mbz = 0; + (void)strcpy(inst, "*"); + if (krb_rd_req(&kt, NFS_KERBSRV, + inst, nsd.nsd_haddr, &kauth, "") == RD_AP_OK && + krb_kntoln(&kauth, lnam) == KSUCCESS && + (pwd = getpwnam(lnam)) != NULL) { + cr = &nsd.nsd_cr; + cr->cr_uid = pwd->pw_uid; + cr->cr_groups[0] = pwd->pw_gid; + cr->cr_ngroups = 1; + setgrent(); + while ((grp = getgrent()) != NULL) { + if (grp->gr_gid == cr->cr_groups[0]) + continue; + for (cpp = grp->gr_mem; + *cpp != NULL; ++cpp) + if (!strcmp(*cpp, lnam)) + break; + if (*cpp == NULL) + continue; + cr->cr_groups[cr->cr_ngroups++] + = grp->gr_gid; + if (cr->cr_ngroups == NGROUPS) + break; + } + endgrent(); + + /* + * Get the timestamp verifier out of the + * authenticator and verifier strings. + */ + kin.t1 = kverf.t1; + kin.t2 = kverf.t2; + kin.w2 = kverf.w2; + bzero((caddr_t)kivec, sizeof (kivec)); + bcopy((caddr_t)kauth.session, + (caddr_t)nsd.nsd_key,sizeof(kauth.session)); + + /* + * Decrypt the timestamp verifier in CBC mode. + */ + XXX + + /* + * Validate the timestamp verifier, to + * check that the session key is ok. + */ + nsd.nsd_timestamp.tv_sec = ntohl(kout.t1); + nsd.nsd_timestamp.tv_usec = ntohl(kout.t2); + nsd.nsd_ttl = ntohl(kout.w1); + if ((nsd.nsd_ttl - 1) == ntohl(kout.w2)) + nfssvc_flag = NFSSVC_NFSD | NFSSVC_AUTHIN; + } +#endif /* NFSKERB */ + } + exit(0); + } + + /* If we are serving udp, set up the socket. */ + if (udpflag) { + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "can't create udp socket"); + exit(1); + } + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(NFS_PORT); + inetaddr.sin_len = sizeof(inetaddr); + if (bind(sock, + (struct sockaddr *)&inetaddr, sizeof(inetaddr)) < 0) { + syslog(LOG_ERR, "can't bind udp addr"); + exit(1); + } + if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_UDP, NFS_PORT) || + !pmap_set(RPCPROG_NFS, 3, IPPROTO_UDP, NFS_PORT)) { + syslog(LOG_ERR, "can't register with udp portmap"); + exit(1); + } + nfsdargs.sock = sock; + nfsdargs.name = NULL; + nfsdargs.namelen = 0; + if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { + syslog(LOG_ERR, "can't Add UDP socket"); + exit(1); + } + (void)close(sock); + } + +#ifdef ISO + /* If we are serving cltp, set up the socket. */ + if (cltpflag) { + if ((sock = socket(AF_ISO, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "can't create cltp socket"); + exit(1); + } + memset(&isoaddr, 0, sizeof(isoaddr)); + isoaddr.siso_family = AF_ISO; + isoaddr.siso_tlen = 2; + cp = TSEL(&isoaddr); + *cp++ = (NFS_PORT >> 8); + *cp = (NFS_PORT & 0xff); + isoaddr.siso_len = sizeof(isoaddr); + if (bind(sock, + (struct sockaddr *)&isoaddr, sizeof(isoaddr)) < 0) { + syslog(LOG_ERR, "can't bind cltp addr"); + exit(1); + } +#ifdef notyet + /* + * XXX + * Someday this should probably use "rpcbind", the son of + * portmap. + */ + if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_UDP, NFS_PORT)) { + syslog(LOG_ERR, "can't register with udp portmap"); + exit(1); + } +#endif /* notyet */ + nfsdargs.sock = sock; + nfsdargs.name = NULL; + nfsdargs.namelen = 0; + if (nfssvc(NFSSVC_ADDSOCK, &nfsdargs) < 0) { + syslog(LOG_ERR, "can't add UDP socket"); + exit(1); + } + close(sock); + } +#endif /* ISO */ + + /* Now set up the master server socket waiting for tcp connections. */ + on = 1; + FD_ZERO(&sockbits); + connect_type_cnt = 0; + if (tcpflag) { + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "can't create tcp socket"); + exit(1); + } + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(NFS_PORT); + inetaddr.sin_len = sizeof(inetaddr); + if (bind(tcpsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { + syslog(LOG_ERR, "can't bind tcp addr"); + exit(1); + } + if (listen(tcpsock, 5) < 0) { + syslog(LOG_ERR, "listen failed"); + exit(1); + } + if (!pmap_set(RPCPROG_NFS, 2, IPPROTO_TCP, NFS_PORT) || + !pmap_set(RPCPROG_NFS, 3, IPPROTO_TCP, NFS_PORT)) { + syslog(LOG_ERR, "can't register tcp with portmap"); + exit(1); + } + FD_SET(tcpsock, &sockbits); + maxsock = tcpsock; + connect_type_cnt++; + } + +#ifdef notyet + /* Now set up the master server socket waiting for tp4 connections. */ + if (tp4flag) { + if ((tp4sock = socket(AF_ISO, SOCK_SEQPACKET, 0)) < 0) { + syslog(LOG_ERR, "can't create tp4 socket"); + exit(1); + } + if (setsockopt(tp4sock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); + memset(&isoaddr, 0, sizeof(isoaddr)); + isoaddr.siso_family = AF_ISO; + isoaddr.siso_tlen = 2; + cp = TSEL(&isoaddr); + *cp++ = (NFS_PORT >> 8); + *cp = (NFS_PORT & 0xff); + isoaddr.siso_len = sizeof(isoaddr); + if (bind(tp4sock, + (struct sockaddr *)&isoaddr, sizeof (isoaddr)) < 0) { + syslog(LOG_ERR, "can't bind tp4 addr"); + exit(1); + } + if (listen(tp4sock, 5) < 0) { + syslog(LOG_ERR, "listen failed"); + exit(1); + } + /* + * XXX + * Someday this should probably use "rpcbind", the son of + * portmap. + */ + if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { + syslog(LOG_ERR, "can't register tcp with portmap"); + exit(1); + } + FD_SET(tp4sock, &sockbits); + maxsock = tp4sock; + connect_type_cnt++; + } + + /* Now set up the master server socket waiting for tpip connections. */ + if (tpipflag) { + if ((tpipsock = socket(AF_INET, SOCK_SEQPACKET, 0)) < 0) { + syslog(LOG_ERR, "can't create tpip socket"); + exit(1); + } + if (setsockopt(tpipsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(NFS_PORT); + inetaddr.sin_len = sizeof(inetaddr); + if (bind(tpipsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { + syslog(LOG_ERR, "can't bind tcp addr"); + exit(1); + } + if (listen(tpipsock, 5) < 0) { + syslog(LOG_ERR, "listen failed"); + exit(1); + } + /* + * XXX + * Someday this should probably use "rpcbind", the son of + * portmap. + */ + if (!pmap_set(RPCPROG_NFS, NFS_VER2, IPPROTO_TCP, NFS_PORT)) { + syslog(LOG_ERR, "can't register tcp with portmap"); + exit(1); + } + FD_SET(tpipsock, &sockbits); + maxsock = tpipsock; + connect_type_cnt++; + } +#endif /* notyet */ + + if (connect_type_cnt == 0) + exit(0); + + setproctitle("master"); + + /* + * Loop forever accepting connections and passing the sockets + * into the kernel for the mounts. + */ + for (;;) { + ready = sockbits; + if (connect_type_cnt > 1) { + if (select(maxsock + 1, + &ready, NULL, NULL, NULL) < 1) { + syslog(LOG_ERR, "select failed: %m"); + exit(1); + } + } + if (tcpflag && FD_ISSET(tcpsock, &ready)) { + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) { + syslog(LOG_ERR, "accept failed: %m"); + exit(1); + } + memset(inetpeer.sin_zero, 0, sizeof(inetpeer.sin_zero)); + if (setsockopt(msgsock, SOL_SOCKET, + SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, + "setsockopt SO_KEEPALIVE: %m"); + nfsdargs.sock = msgsock; + nfsdargs.name = (caddr_t)&inetpeer; + nfsdargs.namelen = sizeof(inetpeer); + nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + (void)close(msgsock); + } +#ifdef notyet + if (tp4flag && FD_ISSET(tp4sock, &ready)) { + len = sizeof(isopeer); + if ((msgsock = accept(tp4sock, + (struct sockaddr *)&isopeer, &len)) < 0) { + syslog(LOG_ERR, "accept failed: %m"); + exit(1); + } + if (setsockopt(msgsock, SOL_SOCKET, + SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, + "setsockopt SO_KEEPALIVE: %m"); + nfsdargs.sock = msgsock; + nfsdargs.name = (caddr_t)&isopeer; + nfsdargs.namelen = len; + nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + (void)close(msgsock); + } + if (tpipflag && FD_ISSET(tpipsock, &ready)) { + len = sizeof(inetpeer); + if ((msgsock = accept(tpipsock, + (struct sockaddr *)&inetpeer, &len)) < 0) { + syslog(LOG_ERR, "Accept failed: %m"); + exit(1); + } + if (setsockopt(msgsock, SOL_SOCKET, + SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt SO_KEEPALIVE: %m"); + nfsdargs.sock = msgsock; + nfsdargs.name = (caddr_t)&inetpeer; + nfsdargs.namelen = len; + nfssvc(NFSSVC_ADDSOCK, &nfsdargs); + (void)close(msgsock); + } +#endif /* notyet */ + } +} + +void +usage() +{ + (void)fprintf(stderr, "usage: nfsd %s\n", USAGE); + exit(1); +} + +void +nonfs(signo) + int signo; +{ + syslog(LOG_ERR, "missing system call: NFS not available."); +} + +void +reapchild(signo) + int signo; +{ + + while (wait3(NULL, WNOHANG, NULL) > 0); +} + +void +setproctitle(a) + char *a; +{ + register char *cp; + char buf[80]; + + cp = Argv[0]; + (void)snprintf(buf, sizeof(buf), "nfsd-%s", a); + (void)strncpy(cp, buf, LastArg - cp); + cp += strlen(cp); + while (cp < LastArg) + *cp++ = '\0'; +} diff --git a/nfsiod.tproj/Makefile b/nfsiod.tproj/Makefile new file mode 100644 index 0000000..fa0ae2f --- /dev/null +++ b/nfsiod.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = nfsiod + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = nfsiod.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.dist nfsiod.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DNFS -DMACH_USER_API +WINDOWS_PB_CFLAGS = -DNFS -DMACH_USER_API +PDO_UNIX_PB_CFLAGS = -DNFS -DMACH_USER_API + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/nfsiod.tproj/Makefile.dist b/nfsiod.tproj/Makefile.dist new file mode 100644 index 0000000..72db42b --- /dev/null +++ b/nfsiod.tproj/Makefile.dist @@ -0,0 +1,7 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= nfsiod +CFLAGS+=-DNFS +MAN8= nfsiod.0 + +.include diff --git a/nfsiod.tproj/Makefile.preamble b/nfsiod.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/nfsiod.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/nfsiod.tproj/PB.project b/nfsiod.tproj/PB.project new file mode 100644 index 0000000..8d6f93f --- /dev/null +++ b/nfsiod.tproj/PB.project @@ -0,0 +1,32 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (nfsiod.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, nfsiod.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = nfsiod; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = nfsiod; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = nfsiod; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = nfsiod; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/nfsiod.tproj/nfsiod.8 b/nfsiod.tproj/nfsiod.8 new file mode 100644 index 0000000..2acd365 --- /dev/null +++ b/nfsiod.tproj/nfsiod.8 @@ -0,0 +1,74 @@ +.\" Copyright (c) 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)nfsiod.8 8.2 (Berkeley) 2/22/94 +.\" +.Dd February 22, 1994 +.Dt NFSIOD 8 +.Os +.Sh NAME +.Nm nfsiod +.Nd local +.Tn NFS +asynchronous I/O server +.Sh SYNOPSIS +.Nm nfsiod +.Op Fl n Ar num_servers +.Sh DESCRIPTION +.Nm Nfsiod +runs on an +.Tn NFS +client machine to service asynchronous I/O requests to its server. +It improves performance but is not required for correct operation. +.Pp +Unless otherwise specified, a single server is started. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl n +Specify how many servers are to be started. +.El +.Pp +A client should run enough daemons to handle its maximum +level of concurrency, typically four to six. +.Pp +The +.Nm nfsiod +utility exits 0 on success, and >0 if an error occurs. +.Sh SEE ALSO +.Xr nfsstat 1 , +.Xr nfssvc 2 , +.Xr mountd 8 , +.Xr portmap 8 +.Sh HISTORY +The +.Nm nfsiod +utility first appeared in 4.4BSD. diff --git a/nfsiod.tproj/nfsiod.c b/nfsiod.tproj/nfsiod.c new file mode 100644 index 0000000..07a87ff --- /dev/null +++ b/nfsiod.tproj/nfsiod.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Global defs */ +#ifdef DEBUG +int debug = 1; +#else +int debug = 0; +#endif + +void nonfs __P((int)); +void reapchild __P((int)); +void usage __P((void)); + +/* + * Nfsiod does asynchronous buffered I/O on behalf of the NFS client. + * It does not have to be running for correct operation, but will + * improve throughput. + */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch, num_servers; + +#define MAXNFSDCNT 20 +#define DEFNFSDCNT 1 + num_servers = DEFNFSDCNT; + while ((ch = getopt(argc, argv, "n:")) != EOF) + switch (ch) { + case 'n': + num_servers = atoi(optarg); + if (num_servers < 1 || num_servers > MAXNFSDCNT) { + warnx("nfsiod count %d; reset to %d", + DEFNFSDCNT); + num_servers = DEFNFSDCNT; + } + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + /* + * XXX + * Backward compatibility, trailing number is the count of daemons. + */ + if (argc > 1) + usage(); + if (argc == 1) { + num_servers = atoi(argv[0]); + if (num_servers < 1 || num_servers > MAXNFSDCNT) { + warnx("nfsiod count %d; reset to %d", DEFNFSDCNT); + num_servers = DEFNFSDCNT; + } + } + + if (debug == 0) { + daemon(0, 0); + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGSYS, nonfs); + } + (void)signal(SIGCHLD, reapchild); + + openlog("nfsiod:", LOG_PID, LOG_DAEMON); + + while (num_servers--) + switch (fork()) { + case -1: + syslog(LOG_ERR, "fork: %m"); + exit (1); + case 0: + if (nfssvc(NFSSVC_BIOD, NULL) < 0) { + syslog(LOG_ERR, "nfssvc: %m"); + exit (1); + } + exit(0); + } + exit (0); +} + +void +nonfs(signo) + int signo; +{ + syslog(LOG_ERR, "missing system call: NFS not available."); +} + +void +reapchild(signo) + int signo; +{ + + while (wait3(NULL, WNOHANG, NULL)); +} + +void +usage() +{ + (void)fprintf(stderr, "usage: nfsiod [-n num_servers]\n"); + exit(1); +} diff --git a/nfsstat.tproj/Makefile b/nfsstat.tproj/Makefile new file mode 100644 index 0000000..d20d30c --- /dev/null +++ b/nfsstat.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = nfsstat + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = nfsstat.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble nfsstat.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DNFS -DMACH_USER_API +WINDOWS_PB_CFLAGS = -DNFS -DMACH_USER_API +PDO_UNIX_PB_CFLAGS = -DNFS -DMACH_USER_API + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/nfsstat.tproj/Makefile.postamble b/nfsstat.tproj/Makefile.postamble new file mode 100644 index 0000000..b5bfe61 --- /dev/null +++ b/nfsstat.tproj/Makefile.postamble @@ -0,0 +1,2 @@ +INSTALL_AS_GROUP = kmem +INSTALL_PERMISSIONS =2555 diff --git a/nfsstat.tproj/Makefile.preamble b/nfsstat.tproj/Makefile.preamble new file mode 100644 index 0000000..925a5c7 --- /dev/null +++ b/nfsstat.tproj/Makefile.preamble @@ -0,0 +1,3 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/nfsstat.tproj/PB.project b/nfsstat.tproj/PB.project new file mode 100644 index 0000000..d4ad122 --- /dev/null +++ b/nfsstat.tproj/PB.project @@ -0,0 +1,31 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (nfsstat.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, nfsstat.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDTOOL = make; + NEXTSTEP_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = make; + PDO_UNIX_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = nfsstat; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = make; + WINDOWS_COMPILEROPTIONS = "-DNFS -DMACH_USER_API"; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/nfsstat.tproj/nfsstat.1 b/nfsstat.tproj/nfsstat.1 new file mode 100644 index 0000000..3acda6c --- /dev/null +++ b/nfsstat.tproj/nfsstat.1 @@ -0,0 +1,88 @@ +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)nfsstat.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt NFSSTAT 1 +.Os BSD 4.4 +.Sh NAME +.Nm nfsstat +.Nd display +.Tn NFS +statistics +.Sh SYNOPSIS +.Nm nfsstat +.Op Fl M Ar core +.Op Fl N Ar system +.Op Fl w Ar wait +.Sh DESCRIPTION +.Nm Nfsstat +displays statistics kept about +.Tn NFS +client and server activity. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl M +Extract values associated with the name list from the specified core +instead of the default +.Pa /dev/kmem . +.It Fl N +Extract the name list from the specified system instead of the default +.Pa /vmunix . +.It Fl w +Display a shorter summary of +.Tn NFS +activity for both the client and server at +.Ar wait +second intervals. +.El +.Sh FILES +.Bl -tag -width /dev/kmem -compact +.It Pa /vmunix +default kernel namelist +.It Pa /dev/kmem +default memory file +.El +.Sh SEE ALSO +.Xr fstat 1 , +.Xr netstat 1 , +.Xr ps 1 , +.Xr systat 1 , +.Xr vmstat 1 , +.Xr iostat 8 , +.Xr pstat 8 , +.Sh HISTORY +The +.Nm nfsstat +command appears in +.Bx 4.4 . diff --git a/nfsstat.tproj/nfsstat.c b/nfsstat.tproj/nfsstat.c new file mode 100644 index 0000000..7bd1ce2 --- /dev/null +++ b/nfsstat.tproj/nfsstat.c @@ -0,0 +1,445 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1997 Apple Computer, Inc. All Rights Reserved + * + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * @(#)nfsstat.c 8.2 (Berkeley) 3/31/95 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHOW_SERVER 0x01 +#define SHOW_CLIENT 0x02 +#define SHOW_ALL (SHOW_SERVER | SHOW_CLIENT) + +struct nlist nl[] = { +#define N_NFSSTAT 0 + { "_nfsstats" }, + {""}, +}; +kvm_t *kd; + +static int deadkernel = 0; + +void intpr __P((u_long, u_int)); +void printhdr __P((void)); +void sidewaysintpr __P((u_int, u_long, u_int)); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + extern char *optarg; + u_int interval; + u_int display = SHOW_ALL; + int ch; + char *memf, *nlistf; + char errbuf[80]; + + interval = 0; + memf = nlistf = NULL; + while ((ch = getopt(argc, argv, "M:N:w:sc")) != EOF) + switch(ch) { + case 'M': + memf = optarg; + break; + case 'N': + nlistf = optarg; + break; + case 'w': + interval = atoi(optarg); + break; + case 's': + display = SHOW_SERVER; + break; + case 'c': + display = SHOW_CLIENT; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + +#define BACKWARD_COMPATIBILITY +#ifdef BACKWARD_COMPATIBILITY + if (*argv) { + interval = atoi(*argv); + if (*++argv) { + nlistf = *argv; + if (*++argv) + memf = *argv; + } + } +#endif + /* + * Discard setgid privileges if not the running kernel so that bad + * guys can't print interesting stuff from kernel memory. + */ + if (nlistf != NULL || memf != NULL) { + setegid(getgid()); + setgid(getgid()); + deadkernel = 1; + + if ((kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, + errbuf)) == 0) { + errx(1, "kvm_openfiles: %s", errbuf); + } + if (kvm_nlist(kd, nl) != 0) { + errx(1, "kvm_nlist: can't get names"); + } + } + + if (interval) + sidewaysintpr(interval, nl[N_NFSSTAT].n_value, display); + else + intpr(nl[N_NFSSTAT].n_value, display); + exit(0); +} + +/* + * Read the nfs stats using sysctl(3) for live kernels, or kvm_read + * for dead ones. + */ +void +readstats(stp) + struct nfsstats *stp; +{ + if(deadkernel) { + if(kvm_read(kd, (u_long)nl[N_NFSSTAT].n_value, stp, + sizeof *stp) < 0) { + err(1, "kvm_read"); + } + } else { + int name[3]; + size_t buflen = sizeof *stp; + struct vfsconf vfc; + extern int getvfsbyname(char *, struct vfsconf *); + + if (getvfsbyname("nfs", &vfc) < 0) + err(1, "getvfsbyname: NFS not compiled into kernel"); + name[0] = CTL_VFS; + name[1] = vfc.vfc_typenum; + name[2] = NFS_NFSSTATS; + if (sysctl(name, 3, stp, &buflen, (void *)0, (size_t)0) < 0) { + err(1, "sysctl"); + } + } +} + +/* + * Print a description of the nfs stats. + */ +void +intpr(nfsstataddr, display) + u_long nfsstataddr; + u_int display; +{ + struct nfsstats nfsstats; + + readstats(&nfsstats); + + if (display & SHOW_CLIENT) { + printf("Client Info:\n"); + printf("Rpc Counts:\n"); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", + "Getattr", "Setattr", "Lookup", "Readlink", "Read", + "Write", "Create", "Remove"); + printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", + nfsstats.rpccnt[NFSPROC_GETATTR], + nfsstats.rpccnt[NFSPROC_SETATTR], + nfsstats.rpccnt[NFSPROC_LOOKUP], + nfsstats.rpccnt[NFSPROC_READLINK], + nfsstats.rpccnt[NFSPROC_READ], + nfsstats.rpccnt[NFSPROC_WRITE], + nfsstats.rpccnt[NFSPROC_CREATE], + nfsstats.rpccnt[NFSPROC_REMOVE]); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", + "Rename", "Link", "Symlink", "Mkdir", "Rmdir", + "Readdir", "RdirPlus", "Access"); + printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", + nfsstats.rpccnt[NFSPROC_RENAME], + nfsstats.rpccnt[NFSPROC_LINK], + nfsstats.rpccnt[NFSPROC_SYMLINK], + nfsstats.rpccnt[NFSPROC_MKDIR], + nfsstats.rpccnt[NFSPROC_RMDIR], + nfsstats.rpccnt[NFSPROC_READDIR], + nfsstats.rpccnt[NFSPROC_READDIRPLUS], + nfsstats.rpccnt[NFSPROC_ACCESS]); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", + "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit", + "GLease", "Vacate", "Evict"); + printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", + nfsstats.rpccnt[NFSPROC_MKNOD], + nfsstats.rpccnt[NFSPROC_FSSTAT], + nfsstats.rpccnt[NFSPROC_FSINFO], + nfsstats.rpccnt[NFSPROC_PATHCONF], + nfsstats.rpccnt[NFSPROC_COMMIT], + nfsstats.rpccnt[NQNFSPROC_GETLEASE], + nfsstats.rpccnt[NQNFSPROC_VACATED], + nfsstats.rpccnt[NQNFSPROC_EVICTED]); + printf("Rpc Info:\n"); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s\n", + "TimedOut", "Invalid", "X Replies", "Retries", "Requests"); + printf("%9d %9d %9d %9d %9d\n", + nfsstats.rpctimeouts, + nfsstats.rpcinvalid, + nfsstats.rpcunexpected, + nfsstats.rpcretries, + nfsstats.rpcrequests); + printf("Cache Info:\n"); + printf("%9.9s %9.9s %9.9s %9.9s", + "Attr Hits", "Misses", "Lkup Hits", "Misses"); + printf(" %9.9s %9.9s %9.9s %9.9s\n", + "BioR Hits", "Misses", "BioW Hits", "Misses"); + printf("%9d %9d %9d %9d", + nfsstats.attrcache_hits, nfsstats.attrcache_misses, + nfsstats.lookupcache_hits, nfsstats.lookupcache_misses); + printf(" %9d %9d %9d %9d\n", + nfsstats.biocache_reads-nfsstats.read_bios, + nfsstats.read_bios, + nfsstats.biocache_writes-nfsstats.write_bios, + nfsstats.write_bios); + printf("%9.9s %9.9s %9.9s %9.9s", + "BioRLHits", "Misses", "BioD Hits", "Misses"); + printf(" %9.9s %9.9s\n", "DirE Hits", "Misses"); + printf("%9d %9d %9d %9d", + nfsstats.biocache_readlinks-nfsstats.readlink_bios, + nfsstats.readlink_bios, + nfsstats.biocache_readdirs-nfsstats.readdir_bios, + nfsstats.readdir_bios); + printf(" %9d %9d\n", + nfsstats.direofcache_hits, nfsstats.direofcache_misses); + } + if (display & SHOW_SERVER) { + printf("\nServer Info:\n"); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", + "Getattr", "Setattr", "Lookup", "Readlink", "Read", + "Write", "Create", "Remove"); + printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", + nfsstats.srvrpccnt[NFSPROC_GETATTR], + nfsstats.srvrpccnt[NFSPROC_SETATTR], + nfsstats.srvrpccnt[NFSPROC_LOOKUP], + nfsstats.srvrpccnt[NFSPROC_READLINK], + nfsstats.srvrpccnt[NFSPROC_READ], + nfsstats.srvrpccnt[NFSPROC_WRITE], + nfsstats.srvrpccnt[NFSPROC_CREATE], + nfsstats.srvrpccnt[NFSPROC_REMOVE]); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", + "Rename", "Link", "Symlink", "Mkdir", "Rmdir", + "Readdir", "RdirPlus", "Access"); + printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", + nfsstats.srvrpccnt[NFSPROC_RENAME], + nfsstats.srvrpccnt[NFSPROC_LINK], + nfsstats.srvrpccnt[NFSPROC_SYMLINK], + nfsstats.srvrpccnt[NFSPROC_MKDIR], + nfsstats.srvrpccnt[NFSPROC_RMDIR], + nfsstats.srvrpccnt[NFSPROC_READDIR], + nfsstats.srvrpccnt[NFSPROC_READDIRPLUS], + nfsstats.srvrpccnt[NFSPROC_ACCESS]); + printf("%9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s\n", + "Mknod", "Fsstat", "Fsinfo", "PathConf", "Commit", + "GLease", "Vacate", "Evict"); + printf("%9d %9d %9d %9d %9d %9d %9d %9d\n", + nfsstats.srvrpccnt[NFSPROC_MKNOD], + nfsstats.srvrpccnt[NFSPROC_FSSTAT], + nfsstats.srvrpccnt[NFSPROC_FSINFO], + nfsstats.srvrpccnt[NFSPROC_PATHCONF], + nfsstats.srvrpccnt[NFSPROC_COMMIT], + nfsstats.srvrpccnt[NQNFSPROC_GETLEASE], + nfsstats.srvrpccnt[NQNFSPROC_VACATED], + nfsstats.srvrpccnt[NQNFSPROC_EVICTED]); + printf("Server Ret-Failed\n"); + printf("%17d\n", nfsstats.srvrpc_errs); + printf("Server Faults\n"); + printf("%13d\n", nfsstats.srv_errs); + printf("Server Cache Stats:\n"); + printf("%9.9s %9.9s %9.9s %9.9s\n", + "Inprog", "Idem", "Non-idem", "Misses"); + printf("%9d %9d %9d %9d\n", + nfsstats.srvcache_inproghits, + nfsstats.srvcache_idemdonehits, + nfsstats.srvcache_nonidemdonehits, + nfsstats.srvcache_misses); + printf("Server Lease Stats:\n"); + printf("%9.9s %9.9s %9.9s\n", + "Leases", "PeakL", "GLeases"); + printf("%9d %9d %9d\n", + nfsstats.srvnqnfs_leases, + nfsstats.srvnqnfs_maxleases, + nfsstats.srvnqnfs_getleases); + printf("Server Write Gathering:\n"); + printf("%9.9s %9.9s %9.9s\n", + "WriteOps", "WriteRPC", "Opsaved"); + printf("%9d %9d %9d\n", + nfsstats.srvvop_writes, + nfsstats.srvrpccnt[NFSPROC_WRITE], + nfsstats.srvrpccnt[NFSPROC_WRITE] - nfsstats.srvvop_writes); + } +} + +u_char signalled; /* set if alarm goes off "early" */ + +/* + * Print a running summary of nfs statistics. + * Repeat display every interval seconds, showing statistics + * collected over that interval. Assumes that interval is non-zero. + * First line printed at top of screen is always cumulative. + */ +void +sidewaysintpr(interval, off, display) + u_int interval; + u_long off; + u_int display; +{ + struct nfsstats nfsstats, lastst; + int hdrcnt, oldmask; + void catchalarm(); + + (void)signal(SIGALRM, catchalarm); + signalled = 0; + (void)alarm(interval); + bzero((caddr_t)&lastst, sizeof(lastst)); + + for (hdrcnt = 1;;) { + if (!--hdrcnt) { + printhdr(); + hdrcnt = 20; + } + readstats(&nfsstats); + if (display & SHOW_CLIENT) + printf("Client: %8d %8d %8d %8d %8d %8d %8d %8d\n", + nfsstats.rpccnt[NFSPROC_GETATTR]-lastst.rpccnt[NFSPROC_GETATTR], + nfsstats.rpccnt[NFSPROC_LOOKUP]-lastst.rpccnt[NFSPROC_LOOKUP], + nfsstats.rpccnt[NFSPROC_READLINK]-lastst.rpccnt[NFSPROC_READLINK], + nfsstats.rpccnt[NFSPROC_READ]-lastst.rpccnt[NFSPROC_READ], + nfsstats.rpccnt[NFSPROC_WRITE]-lastst.rpccnt[NFSPROC_WRITE], + nfsstats.rpccnt[NFSPROC_RENAME]-lastst.rpccnt[NFSPROC_RENAME], + nfsstats.rpccnt[NFSPROC_ACCESS]-lastst.rpccnt[NFSPROC_ACCESS], + (nfsstats.rpccnt[NFSPROC_READDIR]-lastst.rpccnt[NFSPROC_READDIR]) + +(nfsstats.rpccnt[NFSPROC_READDIRPLUS]-lastst.rpccnt[NFSPROC_READDIRPLUS])); + if (display & SHOW_SERVER) + printf("Server: %8d %8d %8d %8d %8d %8d %8d %8d\n", + nfsstats.srvrpccnt[NFSPROC_GETATTR]-lastst.srvrpccnt[NFSPROC_GETATTR], + nfsstats.srvrpccnt[NFSPROC_LOOKUP]-lastst.srvrpccnt[NFSPROC_LOOKUP], + nfsstats.srvrpccnt[NFSPROC_READLINK]-lastst.srvrpccnt[NFSPROC_READLINK], + nfsstats.srvrpccnt[NFSPROC_READ]-lastst.srvrpccnt[NFSPROC_READ], + nfsstats.srvrpccnt[NFSPROC_WRITE]-lastst.srvrpccnt[NFSPROC_WRITE], + nfsstats.srvrpccnt[NFSPROC_RENAME]-lastst.srvrpccnt[NFSPROC_RENAME], + nfsstats.srvrpccnt[NFSPROC_ACCESS]-lastst.srvrpccnt[NFSPROC_ACCESS], + (nfsstats.srvrpccnt[NFSPROC_READDIR]-lastst.srvrpccnt[NFSPROC_READDIR]) + +(nfsstats.srvrpccnt[NFSPROC_READDIRPLUS]-lastst.srvrpccnt[NFSPROC_READDIRPLUS])); + lastst = nfsstats; + fflush(stdout); + oldmask = sigblock(sigmask(SIGALRM)); + if (!signalled) + sigpause(0); + sigsetmask(oldmask); + signalled = 0; + (void)alarm(interval); + } + /*NOTREACHED*/ +} + +void +printhdr() +{ + printf(" %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s %8.8s\n", + "Getattr", "Lookup", "Readlink", "Read", "Write", "Rename", + "Access", "Readdir"); + fflush(stdout); +} + +/* + * Called if an interval expires before sidewaysintpr has completed a loop. + * Sets a flag to not wait for the alarm. + */ +void +catchalarm() +{ + signalled = 1; +} + +void +usage() +{ + (void)fprintf(stderr, + "usage: nfsstat [-cs] [-M core] [-N system] [-w interval]\n"); + exit(1); +} diff --git a/pcap/Makefile b/pcap/Makefile new file mode 100644 index 0000000..9f3d6f9 --- /dev/null +++ b/pcap/Makefile @@ -0,0 +1,63 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = pcap + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Library + +HFILES = ethertype.h gencode.h pcap-int.h pcap-namedb.h pcap.h + +OTHERLINKED = grammar.y scanner.l + +CFILES = bpf_filter.c bpf_image.c etherent.c gencode.c inet.c\ + nametoaddr.c optimize.c pcap-bpf.c pcap.c savefile.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + +OTHERLINKEDOFILES = grammar.o scanner.o + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CURRENTLY_ACTIVE_VERSION = YES +DEPLOY_WITH_VERSION_NAME = A +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = library.make +NEXTSTEP_INSTALLDIR = /usr/lib +WINDOWS_INSTALLDIR = LOCAL_DEVELOPER_DIR/Libraries +PDO_UNIX_INSTALLDIR = /usr/lib +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -traditional-cpp +PROJECT_HEADERS = pcap.h pcap-namedb.h + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD + +WINDOWS_PUBLIC_HEADERS_DIR = LOCAL_DEVELOPER_DIR/Headers/$(NAME) + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/pcap/Makefile.postamble b/pcap/Makefile.postamble new file mode 100644 index 0000000..36381d4 --- /dev/null +++ b/pcap/Makefile.postamble @@ -0,0 +1,122 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/pcap/Makefile.preamble b/pcap/Makefile.preamble new file mode 100644 index 0000000..0e03ce1 --- /dev/null +++ b/pcap/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS += -seg1addr 0x59400000 +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/pcap/PB.project b/pcap/PB.project new file mode 100644 index 0000000..cb13890 --- /dev/null +++ b/pcap/PB.project @@ -0,0 +1,48 @@ +{ + CURRENTLY_ACTIVE_VERSION = YES; + DEPLOY_WITH_VERSION_NAME = A; + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + CLASSES = (); + FRAMEWORKS = (); + H_FILES = (ethertype.h, gencode.h, "pcap-int.h", "pcap-namedb.h", pcap.h); + OTHER_LINKED = ( + bpf_filter.c, + bpf_image.c, + etherent.c, + gencode.c, + grammar.y, + inet.c, + nametoaddr.c, + optimize.c, + "pcap-bpf.c", + pcap.c, + savefile.c, + scanner.l + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + PROJECT_HEADERS = (pcap.h, "pcap-namedb.h"); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-traditional-cpp"; + NEXTSTEP_INSTALLDIR = /usr/lib; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = /bin/gnumake; + PDO_UNIX_INSTALLDIR = /usr/lib; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = pcap; + PROJECTTYPE = Library; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_INSTALLDIR = LOCAL_DEVELOPER_DIR/Libraries; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; + WINDOWS_PUBLICHEADERSDIR = "LOCAL_DEVELOPER_DIR/Headers/$(NAME)"; +} diff --git a/pcap/bpf_filter.c b/pcap/bpf_filter.c new file mode 100644 index 0000000..dca0d0a --- /dev/null +++ b/pcap/bpf_filter.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include + +#if defined(sparc) || defined(hppa) +#define BPF_ALIGN +#endif + +#ifndef BPF_ALIGN +#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) +#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p)) +#else +#define EXTRACT_SHORT(p)\ + ((u_short)\ + ((u_short)*((u_char *)p+0)<<8|\ + (u_short)*((u_char *)p+1)<<0)) +#define EXTRACT_LONG(p)\ + ((u_int32_t)*((u_char *)p+0)<<24|\ + (u_int32_t)*((u_char *)p+1)<<16|\ + (u_int32_t)*((u_char *)p+2)<<8|\ + (u_int32_t)*((u_char *)p+3)<<0) +#endif + +#ifdef KERNEL +#include +#define MINDEX(m, k) \ +{ \ + register int len = m->m_len; \ + \ + while (k >= len) { \ + k -= len; \ + m = m->m_next; \ + if (m == 0) \ + return 0; \ + len = m->m_len; \ + } \ +} + +static int +m_xword(m, k, err) + register struct mbuf *m; + register int k, *err; +{ + register int len; + register u_char *cp, *np; + register struct mbuf *m0; + + len = m->m_len; + while (k >= len) { + k -= len; + m = m->m_next; + if (m == 0) + goto bad; + len = m->m_len; + } + cp = mtod(m, u_char *) + k; + if (len - k >= 4) { + *err = 0; + return EXTRACT_LONG(cp); + } + m0 = m->m_next; + if (m0 == 0 || m0->m_len + len - k < 4) + goto bad; + *err = 0; + np = mtod(m0, u_char *); + switch (len - k) { + + case 1: + return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; + + case 2: + return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) | + np[1]; + + default: + return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) | + np[0]; + } + bad: + *err = 1; + return 0; +} + +static int +m_xhalf(m, k, err) + register struct mbuf *m; + register int k, *err; +{ + register int len; + register u_char *cp; + register struct mbuf *m0; + + len = m->m_len; + while (k >= len) { + k -= len; + m = m->m_next; + if (m == 0) + goto bad; + len = m->m_len; + } + cp = mtod(m, u_char *) + k; + if (len - k >= 2) { + *err = 0; + return EXTRACT_SHORT(cp); + } + m0 = m->m_next; + if (m0 == 0) + goto bad; + *err = 0; + return (cp[k] << 8) | mtod(m0, u_char *)[0]; + bad: + *err = 1; + return 0; +} +#endif + +#include + +/* + * Execute the filter program starting at pc on the packet p + * wirelen is the length of the original packet + * buflen is the amount of data present + */ +u_int +bpf_filter(pc, p, wirelen, buflen) + register struct bpf_insn *pc; + register u_char *p; + u_int wirelen; + register u_int buflen; +{ + register u_int32_t A, X; + register int k; + int32_t mem[BPF_MEMWORDS]; + + if (pc == 0) + /* + * No filter means accept all. + */ + return (u_int)-1; +#ifdef lint + A = 0; + X = 0; +#endif + --pc; + while (1) { + ++pc; + switch (pc->code) { + + default: +#ifdef KERNEL + return 0; +#else + abort(); +#endif + case BPF_RET|BPF_K: + return (u_int)pc->k; + + case BPF_RET|BPF_A: + return (u_int)A; + + case BPF_LD|BPF_W|BPF_ABS: + k = pc->k; + if (k + sizeof(int32_t) > buflen) { +#ifdef KERNEL + int merr; + + if (buflen != 0) + return 0; + A = m_xword((struct mbuf *)p, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } +#ifdef BPF_ALIGN + if (((int)(p + k) & 3) != 0) + A = EXTRACT_LONG(&p[k]); + else +#endif + A = ntohl(*(long *)(p + k)); + continue; + + case BPF_LD|BPF_H|BPF_ABS: + k = pc->k; + if (k + sizeof(short) > buflen) { +#ifdef KERNEL + int merr; + + if (buflen != 0) + return 0; + A = m_xhalf((struct mbuf *)p, k, &merr); + continue; +#else + return 0; +#endif + } + A = EXTRACT_SHORT(&p[k]); + continue; + + case BPF_LD|BPF_B|BPF_ABS: + k = pc->k; + if (k >= buflen) { +#ifdef KERNEL + register struct mbuf *m; + + if (buflen != 0) + return 0; + m = (struct mbuf *)p; + MINDEX(m, k); + A = mtod(m, u_char *)[k]; + continue; +#else + return 0; +#endif + } + A = p[k]; + continue; + + case BPF_LD|BPF_W|BPF_LEN: + A = wirelen; + continue; + + case BPF_LDX|BPF_W|BPF_LEN: + X = wirelen; + continue; + + case BPF_LD|BPF_W|BPF_IND: + k = X + pc->k; + if (k + sizeof(int32_t) > buflen) { +#ifdef KERNEL + int merr; + + if (buflen != 0) + return 0; + A = m_xword((struct mbuf *)p, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } +#ifdef BPF_ALIGN + if (((int)(p + k) & 3) != 0) + A = EXTRACT_LONG(&p[k]); + else +#endif + A = ntohl(*(long *)(p + k)); + continue; + + case BPF_LD|BPF_H|BPF_IND: + k = X + pc->k; + if (k + sizeof(short) > buflen) { +#ifdef KERNEL + int merr; + + if (buflen != 0) + return 0; + A = m_xhalf((struct mbuf *)p, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } + A = EXTRACT_SHORT(&p[k]); + continue; + + case BPF_LD|BPF_B|BPF_IND: + k = X + pc->k; + if (k >= buflen) { +#ifdef KERNEL + register struct mbuf *m; + + if (buflen != 0) + return 0; + m = (struct mbuf *)p; + MINDEX(m, k); + A = mtod(m, char *)[k]; + continue; +#else + return 0; +#endif + } + A = p[k]; + continue; + + case BPF_LDX|BPF_MSH|BPF_B: + k = pc->k; + if (k >= buflen) { +#ifdef KERNEL + register struct mbuf *m; + + if (buflen != 0) + return 0; + m = (struct mbuf *)p; + MINDEX(m, k); + X = (mtod(m, char *)[k] & 0xf) << 2; + continue; +#else + return 0; +#endif + } + X = (p[pc->k] & 0xf) << 2; + continue; + + case BPF_LD|BPF_IMM: + A = pc->k; + continue; + + case BPF_LDX|BPF_IMM: + X = pc->k; + continue; + + case BPF_LD|BPF_MEM: + A = mem[pc->k]; + continue; + + case BPF_LDX|BPF_MEM: + X = mem[pc->k]; + continue; + + case BPF_ST: + mem[pc->k] = A; + continue; + + case BPF_STX: + mem[pc->k] = X; + continue; + + case BPF_JMP|BPF_JA: + pc += pc->k; + continue; + + case BPF_JMP|BPF_JGT|BPF_K: + pc += (A > pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_K: + pc += (A >= pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_K: + pc += (A == pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_K: + pc += (A & pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGT|BPF_X: + pc += (A > X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_X: + pc += (A >= X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_X: + pc += (A == X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_X: + pc += (A & X) ? pc->jt : pc->jf; + continue; + + case BPF_ALU|BPF_ADD|BPF_X: + A += X; + continue; + + case BPF_ALU|BPF_SUB|BPF_X: + A -= X; + continue; + + case BPF_ALU|BPF_MUL|BPF_X: + A *= X; + continue; + + case BPF_ALU|BPF_DIV|BPF_X: + if (X == 0) + return 0; + A /= X; + continue; + + case BPF_ALU|BPF_AND|BPF_X: + A &= X; + continue; + + case BPF_ALU|BPF_OR|BPF_X: + A |= X; + continue; + + case BPF_ALU|BPF_LSH|BPF_X: + A <<= X; + continue; + + case BPF_ALU|BPF_RSH|BPF_X: + A >>= X; + continue; + + case BPF_ALU|BPF_ADD|BPF_K: + A += pc->k; + continue; + + case BPF_ALU|BPF_SUB|BPF_K: + A -= pc->k; + continue; + + case BPF_ALU|BPF_MUL|BPF_K: + A *= pc->k; + continue; + + case BPF_ALU|BPF_DIV|BPF_K: + A /= pc->k; + continue; + + case BPF_ALU|BPF_AND|BPF_K: + A &= pc->k; + continue; + + case BPF_ALU|BPF_OR|BPF_K: + A |= pc->k; + continue; + + case BPF_ALU|BPF_LSH|BPF_K: + A <<= pc->k; + continue; + + case BPF_ALU|BPF_RSH|BPF_K: + A >>= pc->k; + continue; + + case BPF_ALU|BPF_NEG: + A = -A; + continue; + + case BPF_MISC|BPF_TAX: + X = A; + continue; + + case BPF_MISC|BPF_TXA: + A = X; + continue; + } + } +} + +#ifdef KERNEL +/* + * Return true if the 'fcode' is a valid filter program. + * The constraints are that each jump be forward and to a valid + * code. The code must terminate with either an accept or reject. + * 'valid' is an array for use by the routine (it must be at least + * 'len' bytes long). + * + * The kernel needs to be able to verify an application's filter code. + * Otherwise, a bogus program could easily crash the system. + */ +int +bpf_validate(f, len) + struct bpf_insn *f; + int len; +{ + register int i; + register struct bpf_insn *p; + + for (i = 0; i < len; ++i) { + /* + * Check that that jumps are forward, and within + * the code block. + */ + p = &f[i]; + if (BPF_CLASS(p->code) == BPF_JMP) { + register int from = i + 1; + + if (BPF_OP(p->code) == BPF_JA) { + if (from + p->k >= len) + return 0; + } + else if (from + p->jt >= len || from + p->jf >= len) + return 0; + } + /* + * Check that memory operations use valid addresses. + */ + if ((BPF_CLASS(p->code) == BPF_ST || + (BPF_CLASS(p->code) == BPF_LD && + (p->code & 0xe0) == BPF_MEM)) && + (p->k >= BPF_MEMWORDS || p->k < 0)) + return 0; + /* + * Check for constant division by 0. + */ + if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) + return 0; + } + return BPF_CLASS(f[len - 1].code) == BPF_RET; +} +#endif diff --git a/pcap/bpf_image.c b/pcap/bpf_image.c new file mode 100644 index 0000000..f5177d9 --- /dev/null +++ b/pcap/bpf_image.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD */ + +/* + * Copyright (c) 1990, 1991, 1992, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) Header: bpf_image.c,v 1.19 95/11/26 14:02:36 leres Exp (LBL)"; +#endif + +#include +#include + +#include + +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +char * +bpf_image(p, n) + struct bpf_insn *p; + int n; +{ + int v; + char *fmt, *op; + static char image[256]; + char operand[64]; + + v = p->k; + switch (p->code) { + + default: + op = "unimp"; + fmt = "0x%x"; + v = p->code; + break; + + case BPF_RET|BPF_K: + op = "ret"; + fmt = "#%d"; + break; + + case BPF_RET|BPF_A: + op = "ret"; + fmt = ""; + break; + + case BPF_LD|BPF_W|BPF_ABS: + op = "ld"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_H|BPF_ABS: + op = "ldh"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_B|BPF_ABS: + op = "ldb"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_W|BPF_LEN: + op = "ld"; + fmt = "#pktlen"; + break; + + case BPF_LD|BPF_W|BPF_IND: + op = "ld"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_H|BPF_IND: + op = "ldh"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_B|BPF_IND: + op = "ldb"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_IMM: + op = "ld"; + fmt = "#0x%x"; + break; + + case BPF_LDX|BPF_IMM: + op = "ldx"; + fmt = "#0x%x"; + break; + + case BPF_LDX|BPF_MSH|BPF_B: + op = "ldxb"; + fmt = "4*([%d]&0xf)"; + break; + + case BPF_LD|BPF_MEM: + op = "ld"; + fmt = "M[%d]"; + break; + + case BPF_LDX|BPF_MEM: + op = "ldx"; + fmt = "M[%d]"; + break; + + case BPF_ST: + op = "st"; + fmt = "M[%d]"; + break; + + case BPF_STX: + op = "stx"; + fmt = "M[%d]"; + break; + + case BPF_JMP|BPF_JA: + op = "ja"; + fmt = "%d"; + v = n + 1 + p->k; + break; + + case BPF_JMP|BPF_JGT|BPF_K: + op = "jgt"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JGE|BPF_K: + op = "jge"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JEQ|BPF_K: + op = "jeq"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JSET|BPF_K: + op = "jset"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JGT|BPF_X: + op = "jgt"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JGE|BPF_X: + op = "jge"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JEQ|BPF_X: + op = "jeq"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JSET|BPF_X: + op = "jset"; + fmt = "x"; + break; + + case BPF_ALU|BPF_ADD|BPF_X: + op = "add"; + fmt = "x"; + break; + + case BPF_ALU|BPF_SUB|BPF_X: + op = "sub"; + fmt = "x"; + break; + + case BPF_ALU|BPF_MUL|BPF_X: + op = "mul"; + fmt = "x"; + break; + + case BPF_ALU|BPF_DIV|BPF_X: + op = "div"; + fmt = "x"; + break; + + case BPF_ALU|BPF_AND|BPF_X: + op = "and"; + fmt = "x"; + break; + + case BPF_ALU|BPF_OR|BPF_X: + op = "or"; + fmt = "x"; + break; + + case BPF_ALU|BPF_LSH|BPF_X: + op = "lsh"; + fmt = "x"; + break; + + case BPF_ALU|BPF_RSH|BPF_X: + op = "rsh"; + fmt = "x"; + break; + + case BPF_ALU|BPF_ADD|BPF_K: + op = "add"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_SUB|BPF_K: + op = "sub"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_MUL|BPF_K: + op = "mul"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_DIV|BPF_K: + op = "div"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_AND|BPF_K: + op = "and"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_OR|BPF_K: + op = "or"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_LSH|BPF_K: + op = "lsh"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_RSH|BPF_K: + op = "rsh"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_NEG: + op = "neg"; + fmt = ""; + break; + + case BPF_MISC|BPF_TAX: + op = "tax"; + fmt = ""; + break; + + case BPF_MISC|BPF_TXA: + op = "txa"; + fmt = ""; + break; + } + (void)sprintf(operand, fmt, v); + (void)sprintf(image, + (BPF_CLASS(p->code) == BPF_JMP && + BPF_OP(p->code) != BPF_JA) ? + "(%03d) %-8s %-16s jt %d\tjf %d" + : "(%03d) %-8s %s", + n, op, operand, n + 1 + p->jt, n + 1 + p->jf); + return image; +} diff --git a/pcap/etherent.c b/pcap/etherent.c new file mode 100644 index 0000000..3b2347e --- /dev/null +++ b/pcap/etherent.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: etherent.c,v 1.5 1996/09/16 02:33:04 tholo Exp $ */ + +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#) Header: etherent.c,v 1.18 95/10/07 03:08:12 leres Exp (LBL)"; +#endif + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +static __inline int xdtoi(int); +static __inline int skip_space(FILE *); +static __inline int skip_line(FILE *); + +/* Hex digit to integer. */ +static __inline int +xdtoi(c) + register int c; +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +static __inline int +skip_space(f) + FILE *f; +{ + int c; + + do { + c = getc(f); + } while (isspace(c) && c != '\n'); + + return c; +} + +static __inline int +skip_line(f) + FILE *f; +{ + int c; + + do + c = getc(f); + while (c != '\n' && c != EOF); + + return c; +} + +struct pcap_etherent * +pcap_next_etherent(FILE *fp) +{ + register int c, d, i; + char *bp; + static struct pcap_etherent e; + + memset((char *)&e, 0, sizeof(e)); + do { + /* Find addr */ + c = skip_space(fp); + if (c == '\n') + continue; + + /* If this is a comment, or first thing on line + cannot be etehrnet address, skip the line. */ + if (!isxdigit(c)) { + c = skip_line(fp); + continue; + } + + /* must be the start of an address */ + for (i = 0; i < 6; i += 1) { + d = xdtoi(c); + c = getc(fp); + if (isxdigit(c)) { + d <<= 4; + d |= xdtoi(c); + c = getc(fp); + } + e.addr[i] = d; + if (c != ':') + break; + c = getc(fp); + } + if (c == EOF) + break; + + /* Must be whitespace */ + if (!isspace(c)) { + c = skip_line(fp); + continue; + } + c = skip_space(fp); + + /* hit end of line... */ + if (c == '\n') + continue; + + if (c == '#') { + c = skip_line(fp); + continue; + } + + /* pick up name */ + bp = e.name; + /* Use 'd' to prevent buffer overflow. */ + d = sizeof(e.name) - 1; + do { + *bp++ = c; + c = getc(fp); + } while (!isspace(c) && c != EOF && --d > 0); + *bp = '\0'; + + /* Eat trailing junk */ + if (c != '\n') + (void)skip_line(fp); + + return &e; + + } while (c != EOF); + + return (NULL); +} diff --git a/pcap/ethertype.h b/pcap/ethertype.h new file mode 100644 index 0000000..0a046fa --- /dev/null +++ b/pcap/ethertype.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD */ +/* $NetBSD: ethertype.h,v 1.2 1995/03/06 11:38:17 mycroft Exp $ */ + +/* + * Copyright (c) 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) Header: ethertype.h,v 1.2 94/06/14 20:03:27 leres Exp (LBL) + */ + +/* Map between Ethernet protocol types and names */ + +/* Add other Ethernet packet types here */ +#ifndef ETHERTYPE_SPRITE +#define ETHERTYPE_SPRITE 0x0500 +#endif +#ifndef ETHERTYPE_MOPDL +#define ETHERTYPE_MOPDL 0x6001 +#endif +#ifndef ETHERTYPE_MOPRC +#define ETHERTYPE_MOPRC 0x6002 +#endif +#ifndef ETHERTYPE_DN +#define ETHERTYPE_DN 0x6003 +#endif +#ifndef ETHERTYPE_LAT +#define ETHERTYPE_LAT 0x6004 +#endif +#ifndef ETHERTYPE_LANBRIDGE +#define ETHERTYPE_LANBRIDGE 0x8038 +#endif +#ifndef ETHERTYPE_DECDNS +#define ETHERTYPE_DECDNS 0x803c +#endif +#ifndef ETHERTYPE_DECDTS +#define ETHERTYPE_DECDTS 0x803e +#endif +#ifndef ETHERTYPE_VEXP +#define ETHERTYPE_VEXP 0x805b +#endif +#ifndef ETHERTYPE_VPROD +#define ETHERTYPE_VPROD 0x805c +#endif +#ifndef ETHERTYPE_LOOPBACK +#define ETHERTYPE_LOOPBACK 0x9000 +#endif + +#ifndef ETHERTYPE_ATALK +#define ETHERTYPE_ATALK 0x809b /* XXX */ +#endif +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 +#endif +#ifndef ETHERTYPE_NS +#define ETHERTYPE_NS 0x0600 +#endif + +#ifndef ETHERTYPE_REVARP +#define ETHERTYPE_REVARP 0x8035 +#endif + diff --git a/pcap/gencode.c b/pcap/gencode.c new file mode 100644 index 0000000..dfcd9e4 --- /dev/null +++ b/pcap/gencode.c @@ -0,0 +1,1843 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: gencode.c,v 1.5 1996/09/16 02:33:05 tholo Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#) Header: gencode.c,v 1.81 96/06/19 23:09:09 leres Exp (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#if __STDC__ +#include +#else +#include +#endif + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +#include "gencode.h" + +#ifndef ETHERTYPE_REVARP +#define ETHERTYPE_REVARP 0x8035 +#endif +#ifndef ETHERTYPE_MOPDL +#define ETHERTYPE_MOPDL 0x6001 +#endif +#ifndef ETHERTYPE_MOPRC +#define ETHERTYPE_MOPRC 0x6002 +#endif +#ifndef ETHERTYPE_DN +#define ETHERTYPE_DN 0x6003 +#endif +#ifndef ETHERTYPE_LAT +#define ETHERTYPE_LAT 0x6004 +#endif + +#define JMP(c) ((c)|BPF_JMP|BPF_K) + +/* Locals */ +static jmp_buf top_ctx; +static pcap_t *bpf_pcap; + +/* XXX */ +#ifdef PCAP_FDDIPAD +int pcap_fddipad = PCAP_FDDIPAD; +#else +int pcap_fddipad; +#endif +#ifndef DLT_ATM_RFC1483 +#define DLT_ATM_RFC1483 11 +#endif + + +/* VARARGS */ +__dead void +#if __STDC__ +bpf_error(const char *fmt, ...) +#else +bpf_error(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; + +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + if (bpf_pcap != NULL) + (void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap); + va_end(ap); + longjmp(top_ctx, 1); + /* NOTREACHED */ +} + +static void init_linktype(int); + +static int alloc_reg(void); +static void free_reg(int); + +static struct block *root; + +/* + * We divy out chunks of memory rather than call malloc each time so + * we don't have to worry about leaking memory. It's probably + * not a big deal if all this memory was wasted but it this ever + * goes into a library that would probably not be a good idea. + */ +#define NCHUNKS 16 +#define CHUNK0SIZE 1024 +struct chunk { + u_int n_left; + void *m; +}; + +static struct chunk chunks[NCHUNKS]; +static int cur_chunk; + +static void *newchunk(u_int); +static void freechunks(void); +static __inline struct block *new_block(int); +static __inline struct slist *new_stmt(int); +static struct block *gen_retblk(int); +static __inline void syntax(void); + +static void backpatch(struct block *, struct block *); +static void merge(struct block *, struct block *); +static struct block *gen_cmp(u_int, u_int, bpf_int32); +static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32); +static struct block *gen_bcmp(u_int, u_int, u_char *); +static struct block *gen_uncond(int); +static __inline struct block *gen_true(void); +static __inline struct block *gen_false(void); +static struct block *gen_linktype(int); +static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); +static struct block *gen_ehostop(u_char *, int); +static struct block *gen_fhostop(u_char *, int); +static struct block *gen_dnhostop(bpf_u_int32, int, u_int); +static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int); +static struct block *gen_gateway(u_char *, bpf_u_int32 **, int, int); +static struct block *gen_ipfrag(void); +static struct block *gen_portatom(int, bpf_int32); +struct block *gen_portop(int, int, int); +static struct block *gen_port(int, int, int); +static int lookup_proto(char *, int); +static struct block *gen_proto(int, int, int); +static bpf_u_int32 net_mask(bpf_u_int32 *); +static struct slist *xfer_to_x(struct arth *); +static struct slist *xfer_to_a(struct arth *); +static struct block *gen_len(int, int); + +static void * +newchunk(n) + u_int n; +{ + struct chunk *cp; + int k, size; + + /* XXX Round up to nearest long. */ + n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); + + cp = &chunks[cur_chunk]; + if (n > cp->n_left) { + ++cp, k = ++cur_chunk; + if (k >= NCHUNKS) + bpf_error("out of memory"); + size = CHUNK0SIZE << k; + cp->m = (void *)malloc(size); + memset((char *)cp->m, 0, size); + cp->n_left = size; + if (n > size) + bpf_error("out of memory"); + } + cp->n_left -= n; + return (void *)((char *)cp->m + cp->n_left); +} + +static void +freechunks() +{ + int i; + + cur_chunk = 0; + for (i = 0; i < NCHUNKS; ++i) + if (chunks[i].m != NULL) { + free(chunks[i].m); + chunks[i].m = NULL; + } +} + +/* + * A strdup whose allocations are freed after code generation is over. + */ +char * +sdup(s) + char *s; +{ + int n = strlen(s) + 1; + char *cp = newchunk(n); + strcpy(cp, s); + return (cp); +} + +static __inline struct block * +new_block(code) + int code; +{ + struct block *p; + + p = (struct block *)newchunk(sizeof(*p)); + p->s.code = code; + p->head = p; + + return p; +} + +static __inline struct slist * +new_stmt(code) + int code; +{ + struct slist *p; + + p = (struct slist *)newchunk(sizeof(*p)); + p->s.code = code; + + return p; +} + +static struct block * +gen_retblk(v) + int v; +{ + struct block *b = new_block(BPF_RET|BPF_K); + + b->s.k = v; + return b; +} + +static __inline void +syntax() +{ + bpf_error("syntax error in filter expression"); +} + +static bpf_u_int32 netmask; +static int snaplen; + +int +pcap_compile(pcap_t *p, struct bpf_program *program, + char *buf, int optimize, bpf_u_int32 mask) +{ + extern int n_errors; + int len; + + n_errors = 0; + root = NULL; + bpf_pcap = p; + if (setjmp(top_ctx)) { + freechunks(); + return (-1); + } + + netmask = mask; + snaplen = pcap_snapshot(p); + + lex_init(buf ? buf : ""); + init_linktype(pcap_datalink(p)); + (void)pcap_parse(); + + if (n_errors) + syntax(); + + if (root == NULL) + root = gen_retblk(snaplen); + + if (optimize) { + bpf_optimize(&root); + if (root == NULL || + (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) + bpf_error("expression rejects all packets"); + } + program->bf_insns = icode_to_fcode(root, &len); + program->bf_len = len; + + freechunks(); + return (0); +} + +/* + * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates + * which of the jt and jf fields has been resolved and which is a pointer + * back to another unresolved block (or nil). At least one of the fields + * in each block is already resolved. + */ +static void +backpatch(list, target) + struct block *list, *target; +{ + struct block *next; + + while (list) { + if (!list->sense) { + next = JT(list); + JT(list) = target; + } else { + next = JF(list); + JF(list) = target; + } + list = next; + } +} + +/* + * Merge the lists in b0 and b1, using the 'sense' field to indicate + * which of jt and jf is the link. + */ +static void +merge(b0, b1) + struct block *b0, *b1; +{ + register struct block **p = &b0; + + /* Find end of list. */ + while (*p) + p = !((*p)->sense) ? &JT(*p) : &JF(*p); + + /* Concatenate the lists. */ + *p = b1; +} + +void +finish_parse(p) + struct block *p; +{ + backpatch(p, gen_retblk(snaplen)); + p->sense = !p->sense; + backpatch(p, gen_retblk(0)); + root = p->head; +} + +void +gen_and(b0, b1) + struct block *b0, *b1; +{ + backpatch(b0, b1->head); + b0->sense = !b0->sense; + b1->sense = !b1->sense; + merge(b1, b0); + b1->sense = !b1->sense; + b1->head = b0->head; +} + +void +gen_or(b0, b1) + struct block *b0, *b1; +{ + b0->sense = !b0->sense; + backpatch(b0, b1->head); + b0->sense = !b0->sense; + merge(b1, b0); + b1->head = b0->head; +} + +void +gen_not(b) + struct block *b; +{ + b->sense = !b->sense; +} + +static struct block * +gen_cmp(offset, size, v) + u_int offset, size; + bpf_int32 v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; + + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + b->s.k = v; + + return b; +} + +static struct block * +gen_mcmp(offset, size, v, mask) + u_int offset, size; + bpf_int32 v; + bpf_u_int32 mask; +{ + struct block *b = gen_cmp(offset, size, v); + struct slist *s; + + if (mask != 0xffffffff) { + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s->s.k = mask; + b->stmts->next = s; + } + return b; +} + +static struct block * +gen_bcmp(offset, size, v) + u_int offset, size; + u_char *v; +{ + struct block *b, *tmp; + + b = NULL; + while (size >= 4) { + u_char *p = &v[size - 4]; + bpf_int32 w = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + tmp = gen_cmp(offset + size - 4, BPF_W, w); + if (b != NULL) + gen_and(b, tmp); + b = tmp; + size -= 4; + } + while (size >= 2) { + u_char *p = &v[size - 2]; + bpf_int32 w = (p[0] << 8) | p[1]; + tmp = gen_cmp(offset + size - 2, BPF_H, w); + if (b != NULL) + gen_and(b, tmp); + b = tmp; + size -= 2; + } + if (size > 0) { + tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]); + if (b != NULL) + gen_and(b, tmp); + b = tmp; + } + return b; +} + +/* + * Various code constructs need to know the layout of the data link + * layer. These variables give the necessary offsets. off_linktype + * is set to -1 for no encapsulation, in which case, IP is assumed. + */ +static u_int off_linktype; +static u_int off_nl; +static int linktype; + +static void +init_linktype(type) + int type; +{ + linktype = type; + + switch (type) { + + case DLT_EN10MB: + off_linktype = 12; + off_nl = 14; + return; + + case DLT_SLIP: + /* + * SLIP doesn't have a link level type. The 16 byte + * header is hacked into our SLIP driver. + */ + off_linktype = -1; + off_nl = 16; + return; + + case DLT_NULL: + off_linktype = -1; + off_nl = 0; + return; + + case DLT_PPP: + off_linktype = 2; + off_nl = 4; + return; + + case DLT_FDDI: + /* + * FDDI doesn't really have a link-level type field. + * We assume that SSAP = SNAP is being used and pick + * out the encapsulated Ethernet type. + */ + off_linktype = 19; +#ifdef PCAP_FDDIPAD + off_linktype += pcap_fddipad; +#endif + off_nl = 21; +#ifdef PCAP_FDDIPAD + off_nl += pcap_fddipad; +#endif + return; + + case DLT_IEEE802: + off_linktype = 20; + off_nl = 22; + return; + + case DLT_ATM_RFC1483: + /* + * assume routed, non-ISO PDUs + * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00) + */ + off_linktype = 6; + off_nl = 8; + return; + } + bpf_error("unknown data link type 0x%x", linktype); + /* NOTREACHED */ +} + +static struct block * +gen_uncond(rsense) + int rsense; +{ + struct block *b; + struct slist *s; + + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = !rsense; + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + + return b; +} + +static __inline struct block * +gen_true() +{ + return gen_uncond(1); +} + +static __inline struct block * +gen_false() +{ + return gen_uncond(0); +} + +static struct block * +gen_linktype(proto) + int proto; +{ + switch (linktype) { + case DLT_SLIP: + if (proto == ETHERTYPE_IP) + return gen_true(); + else + return gen_false(); + + case DLT_PPP: + if (proto == ETHERTYPE_IP) + proto = 0x0021; /* XXX - need ppp.h defs */ + break; + + case DLT_NULL: + /* XXX */ + if (proto == ETHERTYPE_IP) + return (gen_cmp(0, BPF_W, (bpf_int32)AF_INET)); + else + return gen_false(); + } + return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); +} + +static struct block * +gen_hostop(addr, mask, dir, proto, src_off, dst_off) + bpf_u_int32 addr; + bpf_u_int32 mask; + int dir, proto; + u_int src_off, dst_off; +{ + struct block *b0, *b1; + u_int offset; + + switch (dir) { + + case Q_SRC: + offset = src_off; + break; + + case Q_DST: + offset = dst_off; + break; + + case Q_AND: + b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); + gen_or(b0, b1); + return b1; + + default: + abort(); + } + b0 = gen_linktype(proto); + b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask); + gen_and(b0, b1); + return b1; +} + +static struct block * +gen_ehostop(eaddr, dir) + u_char *eaddr; + int dir; +{ + struct block *b0, *b1; + + switch (dir) { + case Q_SRC: + return gen_bcmp(6, 6, eaddr); + + case Q_DST: + return gen_bcmp(0, 6, eaddr); + + case Q_AND: + b0 = gen_ehostop(eaddr, Q_SRC); + b1 = gen_ehostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ehostop(eaddr, Q_SRC); + b1 = gen_ehostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +/* + * Like gen_ehostop, but for DLT_FDDI + */ +static struct block * +gen_fhostop(eaddr, dir) + u_char *eaddr; + int dir; +{ + struct block *b0, *b1; + + switch (dir) { + case Q_SRC: +#ifdef PCAP_FDDIPAD + return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr); +#else + return gen_bcmp(6 + 1, 6, eaddr); +#endif + + case Q_DST: +#ifdef PCAP_FDDIPAD + return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr); +#else + return gen_bcmp(0 + 1, 6, eaddr); +#endif + + case Q_AND: + b0 = gen_fhostop(eaddr, Q_SRC); + b1 = gen_fhostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_fhostop(eaddr, Q_SRC); + b1 = gen_fhostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +/* + * This is quite tricky because there may be pad bytes in front of the + * DECNET header, and then there are two possible data packet formats that + * carry both src and dst addresses, plus 5 packet types in a format that + * carries only the src node, plus 2 types that use a different format and + * also carry just the src node. + * + * Yuck. + * + * Instead of doing those all right, we just look for data packets with + * 0 or 1 bytes of padding. If you want to look at other packets, that + * will require a lot more hacking. + * + * To add support for filtering on DECNET "areas" (network numbers) + * one would want to add a "mask" argument to this routine. That would + * make the filter even more inefficient, although one could be clever + * and not generate masking instructions if the mask is 0xFFFF. + */ +static struct block * +gen_dnhostop(addr, dir, base_off) + bpf_u_int32 addr; + int dir; + u_int base_off; +{ + struct block *b0, *b1, *b2, *tmp; + u_int offset_lh; /* offset if long header is received */ + u_int offset_sh; /* offset if short header is received */ + + switch (dir) { + + case Q_DST: + offset_sh = 1; /* follows flags */ + offset_lh = 7; /* flgs,darea,dsubarea,HIORD */ + break; + + case Q_SRC: + offset_sh = 3; /* follows flags, dstnode */ + offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */ + break; + + case Q_AND: + /* Inefficient because we do our Calvinball dance twice */ + b0 = gen_dnhostop(addr, Q_SRC, base_off); + b1 = gen_dnhostop(addr, Q_DST, base_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + /* Inefficient because we do our Calvinball dance twice */ + b0 = gen_dnhostop(addr, Q_SRC, base_off); + b1 = gen_dnhostop(addr, Q_DST, base_off); + gen_or(b0, b1); + return b1; + + default: + abort(); + } + b0 = gen_linktype(ETHERTYPE_DN); + /* Check for pad = 1, long header case */ + tmp = gen_mcmp(base_off + 2, BPF_H, + (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); + b1 = gen_cmp(base_off + 2 + 1 + offset_lh, + BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b1); + /* Check for pad = 0, long header case */ + tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); + b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b2); + gen_or(b2, b1); + /* Check for pad = 1, short header case */ + tmp = gen_mcmp(base_off + 2, BPF_H, + (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); + b2 = gen_cmp(base_off + 2 + 1 + offset_sh, + BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b2); + gen_or(b2, b1); + /* Check for pad = 0, short header case */ + tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); + b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b2); + gen_or(b2, b1); + + /* Combine with test for linktype */ + gen_and(b0, b1); + return b1; +} + +static struct block * +gen_host(addr, mask, proto, dir) + bpf_u_int32 addr; + bpf_u_int32 mask; + int proto; + int dir; +{ + struct block *b0, *b1; + + switch (proto) { + + case Q_DEFAULT: + b0 = gen_host(addr, mask, Q_IP, dir); + b1 = gen_host(addr, mask, Q_ARP, dir); + gen_or(b0, b1); + b0 = gen_host(addr, mask, Q_RARP, dir); + gen_or(b1, b0); + return b0; + + case Q_IP: + return gen_hostop(addr, mask, dir, ETHERTYPE_IP, + off_nl + 12, off_nl + 16); + + case Q_RARP: + return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, + off_nl + 14, off_nl + 24); + + case Q_ARP: + return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, + off_nl + 14, off_nl + 24); + + case Q_TCP: + bpf_error("'tcp' modifier applied to host"); + + case Q_UDP: + bpf_error("'udp' modifier applied to host"); + + case Q_ICMP: + bpf_error("'icmp' modifier applied to host"); + + case Q_IGMP: + bpf_error("'igmp' modifier applied to host"); + + case Q_DECNET: + return gen_dnhostop(addr, dir, off_nl); + + case Q_LAT: + bpf_error("LAT host filtering not implemented"); + + case Q_MOPDL: + bpf_error("MOPDL host filtering not implemented"); + + case Q_MOPRC: + bpf_error("MOPRC host filtering not implemented"); + + default: + abort(); + } + /* NOTREACHED */ +} + +static struct block * +gen_gateway(eaddr, alist, proto, dir) + u_char *eaddr; + bpf_u_int32 **alist; + int proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + if (dir != 0) + bpf_error("direction applied to 'gateway'"); + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + case Q_ARP: + case Q_RARP: + if (linktype == DLT_EN10MB) + b0 = gen_ehostop(eaddr, Q_OR); + else if (linktype == DLT_FDDI) + b0 = gen_fhostop(eaddr, Q_OR); + else + bpf_error( + "'gateway' supported only on ethernet or FDDI"); + + b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR); + while (*alist) { + tmp = gen_host(**alist++, 0xffffffffL, proto, Q_OR); + gen_or(b1, tmp); + b1 = tmp; + } + gen_not(b1); + gen_and(b0, b1); + return b1; + } + bpf_error("illegal modifier of 'gateway'"); + /* NOTREACHED */ +} + +struct block * +gen_proto_abbrev(proto) + int proto; +{ + struct block *b0, *b1; + + switch (proto) { + + case Q_TCP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_TCP); + gen_and(b0, b1); + break; + + case Q_UDP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_UDP); + gen_and(b0, b1); + break; + + case Q_ICMP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)IPPROTO_ICMP); + gen_and(b0, b1); + break; + + case Q_IGMP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)2); + gen_and(b0, b1); + break; + + case Q_IP: + b1 = gen_linktype(ETHERTYPE_IP); + break; + + case Q_ARP: + b1 = gen_linktype(ETHERTYPE_ARP); + break; + + case Q_RARP: + b1 = gen_linktype(ETHERTYPE_REVARP); + break; + + case Q_LINK: + bpf_error("link layer applied in wrong context"); + + case Q_DECNET: + b1 = gen_linktype(ETHERTYPE_DN); + break; + + case Q_LAT: + b1 = gen_linktype(ETHERTYPE_LAT); + break; + + case Q_MOPDL: + b1 = gen_linktype(ETHERTYPE_MOPDL); + break; + + case Q_MOPRC: + b1 = gen_linktype(ETHERTYPE_MOPRC); + break; + + default: + abort(); + } + return b1; +} + +static struct block * +gen_ipfrag() +{ + struct slist *s; + struct block *b; + + /* not ip frag */ + s = new_stmt(BPF_LD|BPF_H|BPF_ABS); + s->s.k = off_nl + 6; + b = new_block(JMP(BPF_JSET)); + b->s.k = 0x1fff; + b->stmts = s; + gen_not(b); + + return b; +} + +static struct block * +gen_portatom(off, v) + int off; + bpf_int32 v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + + s->next = new_stmt(BPF_LD|BPF_IND|BPF_H); + s->next->s.k = off_nl + off; + + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + b->s.k = v; + + return b; +} + +struct block * +gen_portop(port, proto, dir) + int port, proto, dir; +{ + struct block *b0, *b1, *tmp; + + /* ip proto 'proto' */ + tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto); + b0 = gen_ipfrag(); + gen_and(tmp, b0); + + switch (dir) { + case Q_SRC: + b1 = gen_portatom(0, (bpf_int32)port); + break; + + case Q_DST: + b1 = gen_portatom(2, (bpf_int32)port); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portatom(0, (bpf_int32)port); + b1 = gen_portatom(2, (bpf_int32)port); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portatom(0, (bpf_int32)port); + b1 = gen_portatom(2, (bpf_int32)port); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_port(port, ip_proto, dir) + int port; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ether proto ip */ + b0 = gen_linktype(ETHERTYPE_IP); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + b1 = gen_portop(port, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portop(port, IPPROTO_TCP, dir); + b1 = gen_portop(port, IPPROTO_UDP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} + +static int +lookup_proto(name, proto) + char *name; + int proto; +{ + int v; + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + v = pcap_nametoproto(name); + if (v == PROTO_UNDEF) + bpf_error("unknown ip proto '%s'", name); + break; + + case Q_LINK: + /* XXX should look up h/w protocol type based on linktype */ + v = pcap_nametoeproto(name); + if (v == PROTO_UNDEF) + bpf_error("unknown ether proto '%s'", name); + break; + + default: + v = PROTO_UNDEF; + break; + } + return v; +} + +static struct block * +gen_proto(v, proto, dir) + int v; + int proto; + int dir; +{ + struct block *b0, *b1; + + if (dir != Q_DEFAULT) + bpf_error("direction applied to 'proto'"); + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v); + gen_and(b0, b1); + return b1; + + case Q_ARP: + bpf_error("arp does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_RARP: + bpf_error("rarp does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_DECNET: + bpf_error("decnet encapsulation is not specifiable"); + /* NOTREACHED */ + + case Q_LAT: + bpf_error("lat does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_MOPRC: + bpf_error("moprc does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_MOPDL: + bpf_error("mopdl does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_LINK: + return gen_linktype(v); + + case Q_UDP: + bpf_error("'udp proto' is bogus"); + /* NOTREACHED */ + + case Q_TCP: + bpf_error("'tcp proto' is bogus"); + /* NOTREACHED */ + + case Q_ICMP: + bpf_error("'icmp proto' is bogus"); + /* NOTREACHED */ + + case Q_IGMP: + bpf_error("'igmp proto' is bogus"); + /* NOTREACHED */ + + default: + abort(); + /* NOTREACHED */ + } + /* NOTREACHED */ +} + +/* + * Left justify 'addr' and return its resulting network mask. + */ +static bpf_u_int32 +net_mask(addr) + bpf_u_int32 *addr; +{ + register bpf_u_int32 m = 0xffffffff; + + if (*addr) + while ((*addr & 0xff000000) == 0) + *addr <<= 8, m <<= 8; + + return m; +} + +struct block * +gen_scode(name, q) + char *name; + struct qual q; +{ + int proto = q.proto; + int dir = q.dir; + u_char *eaddr; + bpf_u_int32 mask, addr, **alist; + struct block *b, *tmp; + int port, real_proto; + + switch (q.addr) { + + case Q_NET: + addr = pcap_nametonetaddr(name); + if (addr == 0) + bpf_error("unknown network '%s'", name); + mask = net_mask(&addr); + return gen_host(addr, mask, proto, dir); + + case Q_DEFAULT: + case Q_HOST: + if (proto == Q_LINK) { + switch (linktype) { + + case DLT_EN10MB: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown ether host '%s'", name); + return gen_ehostop(eaddr, dir); + + case DLT_FDDI: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown FDDI host '%s'", name); + return gen_fhostop(eaddr, dir); + + default: + bpf_error( + "only ethernet/FDDI supports link-level host name"); + break; + } + } else if (proto == Q_DECNET) { + unsigned short dn_addr = __pcap_nametodnaddr(name); + /* + * I don't think DECNET hosts can be multihomed, so + * there is no need to build up a list of addresses + */ + return (gen_host(dn_addr, 0, proto, dir)); + } else { + alist = pcap_nametoaddr(name); + if (alist == NULL || *alist == NULL) + bpf_error("unknown host '%s'", name); + b = gen_host(**alist++, 0xffffffffL, proto, dir); + while (*alist) { + tmp = gen_host(**alist++, 0xffffffffL, + proto, dir); + gen_or(b, tmp); + b = tmp; + } + return b; + } + + case Q_PORT: + if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) + bpf_error("illegal qualifier of 'port'"); + if (pcap_nametoport(name, &port, &real_proto) == 0) + bpf_error("unknown port '%s'", name); + if (proto == Q_UDP) { + if (real_proto == IPPROTO_TCP) + bpf_error("port '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_UDP; + } + if (proto == Q_TCP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port '%s' is udp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_TCP; + } + return gen_port(port, real_proto, dir); + + case Q_GATEWAY: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error("unknown ether host: %s", name); + + alist = pcap_nametoaddr(name); + if (alist == NULL || *alist == NULL) + bpf_error("unknown host '%s'", name); + return gen_gateway(eaddr, alist, proto, dir); + + case Q_PROTO: + real_proto = lookup_proto(name, proto); + if (real_proto >= 0) + return gen_proto(real_proto, proto, dir); + else + bpf_error("unknown protocol: %s", name); + + case Q_UNDEF: + syntax(); + /* NOTREACHED */ + } + abort(); + /* NOTREACHED */ +} + +struct block * +gen_ncode(v, q) + bpf_u_int32 v; + struct qual q; +{ + bpf_u_int32 mask; + int proto = q.proto; + int dir = q.dir; + + switch (q.addr) { + + case Q_DEFAULT: + case Q_HOST: + case Q_NET: + if (proto == Q_DECNET) + return gen_host(v, 0, proto, dir); + else if (proto == Q_LINK) { + bpf_error("illegal link layer address"); + } else { + mask = net_mask(&v); + return gen_host(v, mask, proto, dir); + } + + case Q_PORT: + if (proto == Q_UDP) + proto = IPPROTO_UDP; + else if (proto == Q_TCP) + proto = IPPROTO_TCP; + else if (proto == Q_DEFAULT) + proto = PROTO_UNDEF; + else + bpf_error("illegal qualifier of 'port'"); + + return gen_port((int)v, proto, dir); + + case Q_GATEWAY: + bpf_error("'gateway' requires a name"); + /* NOTREACHED */ + + case Q_PROTO: + return gen_proto((int)v, proto, dir); + + case Q_UNDEF: + syntax(); + /* NOTREACHED */ + + default: + abort(); + /* NOTREACHED */ + } + /* NOTREACHED */ +} + +struct block * +gen_ecode(eaddr, q) + u_char *eaddr; + struct qual q; +{ + if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { + if (linktype == DLT_EN10MB) + return gen_ehostop(eaddr, (int)q.dir); + if (linktype == DLT_FDDI) + return gen_fhostop(eaddr, (int)q.dir); + } + bpf_error("ethernet address used in non-ether expression"); + /* NOTREACHED */ +} + +void +sappend(s0, s1) + struct slist *s0, *s1; +{ + /* + * This is definitely not the best way to do this, but the + * lists will rarely get long. + */ + while (s0->next) + s0 = s0->next; + s0->next = s1; +} + +static struct slist * +xfer_to_x(a) + struct arth *a; +{ + struct slist *s; + + s = new_stmt(BPF_LDX|BPF_MEM); + s->s.k = a->regno; + return s; +} + +static struct slist * +xfer_to_a(a) + struct arth *a; +{ + struct slist *s; + + s = new_stmt(BPF_LD|BPF_MEM); + s->s.k = a->regno; + return s; +} + +struct arth * +gen_load(proto, index, size) + int proto; + struct arth *index; + int size; +{ + struct slist *s, *tmp; + struct block *b; + int regno = alloc_reg(); + + free_reg(index->regno); + switch (size) { + + default: + bpf_error("data size must be 1, 2, or 4"); + + case 1: + size = BPF_B; + break; + + case 2: + size = BPF_H; + break; + + case 4: + size = BPF_W; + break; + } + switch (proto) { + default: + bpf_error("unsupported index operation"); + + case Q_LINK: + s = xfer_to_x(index); + tmp = new_stmt(BPF_LD|BPF_IND|size); + sappend(s, tmp); + sappend(index->s, s); + break; + + case Q_IP: + case Q_ARP: + case Q_RARP: + case Q_DECNET: + case Q_LAT: + case Q_MOPRC: + case Q_MOPDL: + /* XXX Note that we assume a fixed link link header here. */ + s = xfer_to_x(index); + tmp = new_stmt(BPF_LD|BPF_IND|size); + tmp->s.k = off_nl; + sappend(s, tmp); + sappend(index->s, s); + + b = gen_proto_abbrev(proto); + if (index->b) + gen_and(index->b, b); + index->b = b; + break; + + case Q_TCP: + case Q_UDP: + case Q_ICMP: + case Q_IGMP: + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + sappend(s, xfer_to_a(index)); + sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); + sappend(s, new_stmt(BPF_MISC|BPF_TAX)); + sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); + tmp->s.k = off_nl; + sappend(index->s, s); + + gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); + if (index->b) + gen_and(index->b, b); + index->b = b; + break; + } + index->regno = regno; + s = new_stmt(BPF_ST); + s->s.k = regno; + sappend(index->s, s); + + return index; +} + +struct block * +gen_relation(code, a0, a1, reversed) + int code; + struct arth *a0, *a1; + int reversed; +{ + struct slist *s0, *s1, *s2; + struct block *b, *tmp; + + s0 = xfer_to_x(a1); + s1 = xfer_to_a(a0); + s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); + b = new_block(JMP(code)); + if (code == BPF_JGT || code == BPF_JGE) { + reversed = !reversed; + b->s.k = 0x80000000; + } + if (reversed) + gen_not(b); + + sappend(s1, s2); + sappend(s0, s1); + sappend(a1->s, s0); + sappend(a0->s, a1->s); + + b->stmts = a0->s; + + free_reg(a0->regno); + free_reg(a1->regno); + + /* 'and' together protocol checks */ + if (a0->b) { + if (a1->b) { + gen_and(a0->b, tmp = a1->b); + } + else + tmp = a0->b; + } else + tmp = a1->b; + + if (tmp) + gen_and(tmp, b); + + return b; +} + +struct arth * +gen_loadlen() +{ + int regno = alloc_reg(); + struct arth *a = (struct arth *)newchunk(sizeof(*a)); + struct slist *s; + + s = new_stmt(BPF_LD|BPF_LEN); + s->next = new_stmt(BPF_ST); + s->next->s.k = regno; + a->s = s; + a->regno = regno; + + return a; +} + +struct arth * +gen_loadi(val) + int val; +{ + struct arth *a; + struct slist *s; + int reg; + + a = (struct arth *)newchunk(sizeof(*a)); + + reg = alloc_reg(); + + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = val; + s->next = new_stmt(BPF_ST); + s->next->s.k = reg; + a->s = s; + a->regno = reg; + + return a; +} + +struct arth * +gen_neg(a) + struct arth *a; +{ + struct slist *s; + + s = xfer_to_a(a); + sappend(a->s, s); + s = new_stmt(BPF_ALU|BPF_NEG); + s->s.k = 0; + sappend(a->s, s); + s = new_stmt(BPF_ST); + s->s.k = a->regno; + sappend(a->s, s); + + return a; +} + +struct arth * +gen_arth(code, a0, a1) + int code; + struct arth *a0, *a1; +{ + struct slist *s0, *s1, *s2; + + s0 = xfer_to_x(a1); + s1 = xfer_to_a(a0); + s2 = new_stmt(BPF_ALU|BPF_X|code); + + sappend(s1, s2); + sappend(s0, s1); + sappend(a1->s, s0); + sappend(a0->s, a1->s); + + free_reg(a1->regno); + + s0 = new_stmt(BPF_ST); + a0->regno = s0->s.k = alloc_reg(); + sappend(a0->s, s0); + + return a0; +} + +/* + * Here we handle simple allocation of the scratch registers. + * If too many registers are alloc'd, the allocator punts. + */ +static int regused[BPF_MEMWORDS]; +static int curreg; + +/* + * Return the next free register. + */ +static int +alloc_reg() +{ + int n = BPF_MEMWORDS; + + while (--n >= 0) { + if (regused[curreg]) + curreg = (curreg + 1) % BPF_MEMWORDS; + else { + regused[curreg] = 1; + return curreg; + } + } + bpf_error("too many registers needed to evaluate expression"); + /* NOTREACHED */ +} + +/* + * Return a register to the table so it can + * be used later. + */ +static void +free_reg(n) + int n; +{ + regused[n] = 0; +} + +static struct block * +gen_len(jmp, n) + int jmp, n; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_LEN); + b = new_block(JMP(jmp)); + b->stmts = s; + b->s.k = n; + + return b; +} + +struct block * +gen_greater(n) + int n; +{ + return gen_len(BPF_JGE, n); +} + +struct block * +gen_less(n) + int n; +{ + struct block *b; + + b = gen_len(BPF_JGT, n); + gen_not(b); + + return b; +} + +struct block * +gen_byteop(op, idx, val) + int op, idx, val; +{ + struct block *b; + struct slist *s; + + switch (op) { + default: + abort(); + + case '=': + return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + + case '<': + b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + b->s.code = JMP(BPF_JGE); + gen_not(b); + return b; + + case '>': + b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + b->s.code = JMP(BPF_JGT); + return b; + + case '|': + s = new_stmt(BPF_ALU|BPF_OR|BPF_K); + break; + + case '&': + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + break; + } + s->s.k = val; + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + gen_not(b); + + return b; +} + +struct block * +gen_broadcast(proto) + int proto; +{ + bpf_u_int32 hostmask; + struct block *b0, *b1, *b2; + static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + switch (proto) { + + case Q_DEFAULT: + case Q_LINK: + if (linktype == DLT_EN10MB) + return gen_ehostop(ebroadcast, Q_DST); + if (linktype == DLT_FDDI) + return gen_fhostop(ebroadcast, Q_DST); + bpf_error("not a broadcast link"); + break; + + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + hostmask = ~netmask; + b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask); + b2 = gen_mcmp(off_nl + 16, BPF_W, + (bpf_int32)(~0 & hostmask), hostmask); + gen_or(b1, b2); + gen_and(b0, b2); + return b2; + } + bpf_error("only ether/ip broadcast filters supported"); +} + +struct block * +gen_multicast(proto) + int proto; +{ + register struct block *b0, *b1; + register struct slist *s; + + switch (proto) { + + case Q_DEFAULT: + case Q_LINK: + if (linktype == DLT_EN10MB) { + /* ether[0] & 1 != 0 */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b0 = new_block(JMP(BPF_JSET)); + b0->s.k = 1; + b0->stmts = s; + return b0; + } + + if (linktype == DLT_FDDI) { + /* XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX */ + /* fddi[1] & 1 != 0 */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b0 = new_block(JMP(BPF_JSET)); + b0->s.k = 1; + b0->stmts = s; + return b0; + } + /* Link not known to support multicasts */ + break; + + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224); + b1->s.code = JMP(BPF_JGE); + gen_and(b0, b1); + return b1; + } + bpf_error("only IP multicast filters supported on ethernet/FDDI"); +} + +/* + * generate command for inbound/outbound. It's here so we can + * make it link-type specific. 'dir' = 0 implies "inbound", + * = 1 implies "outbound". + */ +struct block * +gen_inbound(dir) + int dir; +{ + register struct block *b0; + + b0 = gen_relation(BPF_JEQ, + gen_load(Q_LINK, gen_loadi(0), 1), + gen_loadi(0), + dir); + return (b0); +} diff --git a/pcap/gencode.h b/pcap/gencode.h new file mode 100644 index 0000000..33cb995 --- /dev/null +++ b/pcap/gencode.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: gencode.h,v 1.4 1996/07/12 13:19:08 mickey Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) Header: gencode.h,v 1.33 96/06/23 02:21:09 leres Exp (LBL) + */ + +/* Address qualifiers. */ + +#define Q_HOST 1 +#define Q_NET 2 +#define Q_PORT 3 +#define Q_GATEWAY 4 +#define Q_PROTO 5 + +/* Protocol qualifiers. */ + +#define Q_LINK 1 +#define Q_IP 2 +#define Q_ARP 3 +#define Q_RARP 4 +#define Q_TCP 5 +#define Q_UDP 6 +#define Q_ICMP 7 +#define Q_IGMP 8 + +#define Q_DECNET 9 +#define Q_LAT 10 +#define Q_MOPRC 11 +#define Q_MOPDL 12 + +/* Directional qualifiers. */ + +#define Q_SRC 1 +#define Q_DST 2 +#define Q_OR 3 +#define Q_AND 4 + +#define Q_DEFAULT 0 +#define Q_UNDEF 255 + +struct stmt { + int code; + bpf_int32 k; +}; + +struct slist { + struct stmt s; + struct slist *next; +}; + +/* + * A bit vector to represent definition sets. We assume TOT_REGISTERS + * is smaller than 8*sizeof(atomset). + */ +typedef bpf_u_int32 atomset; +#define ATOMMASK(n) (1 << (n)) +#define ATOMELEM(d, n) (d & ATOMMASK(n)) + +/* + * An unbounded set. + */ +typedef bpf_u_int32 *uset; + +/* + * Total number of atomic entities, including accumulator (A) and index (X). + * We treat all these guys similarly during flow analysis. + */ +#define N_ATOMS (BPF_MEMWORDS+2) + +struct edge { + int id; + int code; + uset edom; + struct block *succ; + struct block *pred; + struct edge *next; /* link list of incoming edges for a node */ +}; + +struct block { + int id; + struct slist *stmts; /* side effect stmts */ + struct stmt s; /* branch stmt */ + int mark; + int longjt; /* jt branch requires long jump */ + int longjf; /* jf branch requires long jump */ + int level; + int offset; + int sense; + struct edge et; + struct edge ef; + struct block *head; + struct block *link; /* link field used by optimizer */ + uset dom; + uset closure; + struct edge *in_edges; + atomset def, kill; + atomset in_use; + atomset out_use; + int oval; + int val[N_ATOMS]; +}; + +struct arth { + struct block *b; /* protocol checks */ + struct slist *s; /* stmt list */ + int regno; /* virtual register number of result */ +}; + +struct qual { + unsigned char addr; + unsigned char proto; + unsigned char dir; + unsigned char pad; +}; + +struct arth *gen_loadi(int); +struct arth *gen_load(int, struct arth *, int); +struct arth *gen_loadlen(void); +struct arth *gen_neg(struct arth *); +struct arth *gen_arth(int, struct arth *, struct arth *); + +void gen_and(struct block *, struct block *); +void gen_or(struct block *, struct block *); +void gen_not(struct block *); + +struct block *gen_scode(char *, struct qual); +struct block *gen_ecode(u_char *, struct qual); +struct block *gen_ncode(bpf_u_int32, struct qual); +struct block *gen_proto_abbrev(int); +struct block *gen_relation(int, struct arth *, struct arth *, int); +struct block *gen_less(int); +struct block *gen_greater(int); +struct block *gen_byteop(int, int, int); +struct block *gen_broadcast(int); +struct block *gen_multicast(int); +struct block *gen_inbound(int); + +void bpf_optimize(struct block **); +#if __STDC__ +__dead void bpf_error(const char *, ...) + __attribute__((volatile, format (printf, 1, 2))); +#endif + +void finish_parse(struct block *); +char *sdup(char *); + +struct bpf_insn *icode_to_fcode(struct block *, int *); +int pcap_parse(void); +void lex_init(char *); +void sappend(struct slist *, struct slist *); + +/* XXX */ +#define JT(b) ((b)->et.succ) +#define JF(b) ((b)->ef.succ) diff --git a/pcap/grammar.y b/pcap/grammar.y new file mode 100644 index 0000000..529ca97 --- /dev/null +++ b/pcap/grammar.y @@ -0,0 +1,280 @@ +%{ +/* $OpenBSD: grammar.y,v 1.4 1996/07/12 13:19:09 mickey Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + */ +#ifndef lint +static char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/pcap/grammar.y,v 1.1.1.1 1999/05/02 03:57:54 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif + +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" +#include "gencode.h" + +#define QSET(q, p, d, a) (q).proto = (p),\ + (q).dir = (d),\ + (q).addr = (a) + +int n_errors = 0; + +static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; + +static void +yyerror(char *msg) +{ + ++n_errors; + bpf_error(msg); + /* NOTREACHED */ +} + +#ifndef YYBISON +int yyparse(void); + +int +pcap_parse() +{ + return (yyparse()); +} +#endif + +%} + +%union { + int i; + u_long h; + u_char *e; + char *s; + struct stmt *stmt; + struct arth *a; + struct { + struct qual q; + struct block *b; + } blk; + struct block *rblk; +} + +%type expr id nid pid term rterm qid +%type head +%type pqual dqual aqual ndaqual +%type arth narth +%type byteop pname pnum relop irelop +%type and or paren not null prog +%type other + +%token DST SRC HOST GATEWAY +%token NET PORT LESS GREATER PROTO BYTE +%token ARP RARP IP TCP UDP ICMP IGMP +%token DECNET LAT MOPRC MOPDL +%token TK_BROADCAST TK_MULTICAST +%token NUM INBOUND OUTBOUND +%token LINK +%token GEQ LEQ NEQ +%token ID EID HID +%token LSH RSH +%token LEN + +%type ID +%type EID +%type HID +%type NUM + +%left OR AND +%nonassoc '!' +%left '|' +%left '&' +%left LSH RSH +%left '+' '-' +%left '*' '/' +%nonassoc UMINUS +%% +prog: null expr +{ + finish_parse($2.b); +} + | null + ; +null: /* null */ { $$.q = qerr; } + ; +expr: term + | expr and term { gen_and($1.b, $3.b); $$ = $3; } + | expr and id { gen_and($1.b, $3.b); $$ = $3; } + | expr or term { gen_or($1.b, $3.b); $$ = $3; } + | expr or id { gen_or($1.b, $3.b); $$ = $3; } + ; +and: AND { $$ = $0; } + ; +or: OR { $$ = $0; } + ; +id: nid + | pnum { $$.b = gen_ncode((u_long)$1, + $$.q = $0.q); } + | paren pid ')' { $$ = $2; } + ; +nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } + | HID { + /* Decide how to parse HID based on proto */ + $$.q = $0.q; + switch ($$.q.proto) { + case Q_DECNET: + $$.b = + gen_ncode(__pcap_atodn((char *)$1), + $$.q); + break; + default: + $$.b = + gen_ncode(__pcap_atoin((char *)$1), + $$.q); + break; + } + } + | EID { $$.b = gen_ecode($1, $$.q = $0.q); } + | not id { gen_not($2.b); $$ = $2; } + ; +not: '!' { $$ = $0; } + ; +paren: '(' { $$ = $0; } + ; +pid: nid + | qid and id { gen_and($1.b, $3.b); $$ = $3; } + | qid or id { gen_or($1.b, $3.b); $$ = $3; } + ; +qid: pnum { $$.b = gen_ncode((u_long)$1, + $$.q = $0.q); } + | pid + ; +term: rterm + | not term { gen_not($2.b); $$ = $2; } + ; +head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } + | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } + | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } + | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } + | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } + ; +rterm: head id { $$ = $2; } + | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } + | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; } + | arth relop arth { $$.b = gen_relation($2, $1, $3, 0); + $$.q = qerr; } + | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1); + $$.q = qerr; } + | other { $$.b = $1; $$.q = qerr; } + ; +/* protocol level qualifiers */ +pqual: pname + | { $$ = Q_DEFAULT; } + ; +/* 'direction' qualifiers */ +dqual: SRC { $$ = Q_SRC; } + | DST { $$ = Q_DST; } + | SRC OR DST { $$ = Q_OR; } + | DST OR SRC { $$ = Q_OR; } + | SRC AND DST { $$ = Q_AND; } + | DST AND SRC { $$ = Q_AND; } + ; +/* address type qualifiers */ +aqual: HOST { $$ = Q_HOST; } + | NET { $$ = Q_NET; } + | PORT { $$ = Q_PORT; } + ; +/* non-directional address type qualifiers */ +ndaqual: GATEWAY { $$ = Q_GATEWAY; } + ; +pname: LINK { $$ = Q_LINK; } + | IP { $$ = Q_IP; } + | ARP { $$ = Q_ARP; } + | RARP { $$ = Q_RARP; } + | TCP { $$ = Q_TCP; } + | UDP { $$ = Q_UDP; } + | ICMP { $$ = Q_ICMP; } + | IGMP { $$ = Q_IGMP; } + | DECNET { $$ = Q_DECNET; } + | LAT { $$ = Q_LAT; } + | MOPDL { $$ = Q_MOPDL; } + | MOPRC { $$ = Q_MOPRC; } + ; +other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } + | pqual TK_MULTICAST { $$ = gen_multicast($1); } + | LESS NUM { $$ = gen_less($2); } + | GREATER NUM { $$ = gen_greater($2); } + | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } + | INBOUND { $$ = gen_inbound(0); } + | OUTBOUND { $$ = gen_inbound(1); } + ; +relop: '>' { $$ = BPF_JGT; } + | GEQ { $$ = BPF_JGE; } + | '=' { $$ = BPF_JEQ; } + ; +irelop: LEQ { $$ = BPF_JGT; } + | '<' { $$ = BPF_JGE; } + | NEQ { $$ = BPF_JEQ; } + ; +arth: pnum { $$ = gen_loadi($1); } + | narth + ; +narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } + | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } + | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } + | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } + | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } + | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } + | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } + | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } + | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } + | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } + | '-' arth %prec UMINUS { $$ = gen_neg($2); } + | paren narth ')' { $$ = $2; } + | LEN { $$ = gen_loadlen(); } + ; +byteop: '&' { $$ = '&'; } + | '|' { $$ = '|'; } + | '<' { $$ = '<'; } + | '>' { $$ = '>'; } + | '=' { $$ = '='; } + ; +pnum: NUM + | paren pnum ')' { $$ = $2; } + ; +%% diff --git a/pcap/inet.c b/pcap/inet.c new file mode 100644 index 0000000..50afec5 --- /dev/null +++ b/pcap/inet.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: inet.c,v 1.6 1997/01/24 19:17:25 deraadt Exp $ */ + +/* + * Copyright (c) 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) Header: inet.c,v 1.16 96/06/23 14:28:22 leres Exp (LBL)"; +#endif + +#include +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +/* Not all systems have IFF_LOOPBACK */ +#ifdef IFF_LOOPBACK +#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) +#else +#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0) +#endif + +/* + * Return the name of a network interface attached to the system, or NULL + * if none can be found. The interface must be configured up; the + * lowest unit number is preferred; loopback is ignored. + */ +char * +pcap_lookupdev(errbuf) + register char *errbuf; +{ + register int fd, minunit, n; + register char *cp, *ibuf = NULL; + register struct ifreq *ifrp, *ifend, *ifnext, *mp; + struct ifconf ifc; + struct ifreq ifr; + static char device[sizeof(ifrp->ifr_name) + 1]; + int len = 8192; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); + return (NULL); + } + while (1) { + ifc.ifc_len = len; + ifc.ifc_buf = ibuf = realloc(ibuf, len); + if (ibuf == NULL) { + close(fd); + return (NULL); + } + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0) { + (void)close(fd); + free(ibuf); + return (NULL); + } + if (ifc.ifc_len + sizeof(ifr) < len) + break; + len *= 2; + } + + ifrp = (struct ifreq *)ibuf; + ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); + + mp = NULL; + minunit = 666; + for (; ifrp < ifend; ifrp = ifnext) { +#if BSD - 0 >= 199006 + n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); + if (n < sizeof(*ifrp)) + ifnext = ifrp + 1; + else + ifnext = (struct ifreq *)((char *)ifrp + n); + if (ifrp->ifr_addr.sa_family != AF_INET) + continue; +#else + ifnext = ifrp + 1; +#endif + /* + * Need a template to preserve address info that is + * used below to locate the next entry. (Otherwise, + * SIOCGIFFLAGS stomps over it because the requests + * are returned in a union.) + */ + strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { + (void)sprintf(errbuf, "SIOCGIFFLAGS: %s", + pcap_strerror(errno)); + (void)close(fd); + free(ibuf); + return (NULL); + } + + /* Must be up and not the loopback */ + if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr)) + continue; + + for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) + continue; + n = atoi(cp); + if (n < minunit) { + minunit = n; + mp = ifrp; + } + } + free(ibuf); + (void)close(fd); + if (mp == NULL) { + (void)strcpy(errbuf, "no suitable device found"); + return (NULL); + } + + (void)strncpy(device, mp->ifr_name, sizeof(device) - 1); + device[sizeof(device) - 1] = '\0'; + return (device); +} + +int +pcap_lookupnet(device, netp, maskp, errbuf) + register char *device; + register bpf_u_int32 *netp, *maskp; + register char *errbuf; +{ + register int fd; + register struct sockaddr_in *sin; + struct ifreq ifr; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); + return (-1); + } + memset(&ifr, 0, sizeof(ifr)); +#ifdef linux + /* XXX Work around Linux kernel bug */ + ifr.ifr_addr.sa_family = AF_INET; +#endif + (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { + (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s", + device, pcap_strerror(errno)); + (void)close(fd); + return (-1); + } + sin = (struct sockaddr_in *)&ifr.ifr_addr; + *netp = sin->sin_addr.s_addr; + if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { + (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s", + device, pcap_strerror(errno)); + (void)close(fd); + return (-1); + } + (void)close(fd); + *maskp = sin->sin_addr.s_addr; + if (*maskp == 0) { + if (IN_CLASSA(*netp)) + *maskp = IN_CLASSA_NET; + else if (IN_CLASSB(*netp)) + *maskp = IN_CLASSB_NET; + else if (IN_CLASSC(*netp)) + *maskp = IN_CLASSC_NET; + else { + (void)sprintf(errbuf, "inet class for 0x%x unknown", + *netp); + return (-1); + } + } + *netp &= *maskp; + return (0); +} diff --git a/pcap/nametoaddr.c b/pcap/nametoaddr.c new file mode 100644 index 0000000..3ce8008 --- /dev/null +++ b/pcap/nametoaddr.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: nametoaddr.c,v 1.5 1996/09/16 02:33:06 tholo Exp $ */ + +/* + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Name to id translation routines used by the scanner. + * These functions are not time critical. + */ + +#ifndef lint +static char rcsid[] = + "@(#) Header: nametoaddr.c,v 1.38 96/06/17 02:42:50 leres Exp (LBL)"; +#endif + +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" +#include "gencode.h" + +#ifndef NTOHL +#define NTOHL(x) (x) = ntohl(x) +#define NTOHS(x) (x) = ntohs(x) +#endif + +static __inline int xdtoi(int); + +/* + * Convert host name to internet address. + * Return 0 upon failure. + */ +bpf_u_int32 ** +pcap_nametoaddr(const char *name) +{ +#ifndef h_addr + static bpf_u_int32 *hlist[2]; +#endif + bpf_u_int32 **p; + struct hostent *hp; + + if ((hp = gethostbyname(name)) != NULL) { +#ifndef h_addr + hlist[0] = (bpf_u_int32 *)hp->h_addr; + NTOHL(hp->h_addr); + return hlist; +#else + for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p) + NTOHL(**p); + return (bpf_u_int32 **)hp->h_addr_list; +#endif + } + else + return 0; +} + +/* + * Convert net name to internet address. + * Return 0 upon failure. + */ +bpf_u_int32 +pcap_nametonetaddr(const char *name) +{ + struct netent *np; + + if ((np = getnetbyname(name)) != NULL) + return np->n_net; + else + return 0; +} + +/* + * Convert a port name to its port and protocol numbers. + * We assume only TCP or UDP. + * Return 0 upon failure. + */ +int +pcap_nametoport(const char *name, int *port, int *proto) +{ + struct servent *sp; + char *other; + + sp = getservbyname(name, (char *)0); + if (sp != NULL) { + NTOHS(sp->s_port); + *port = sp->s_port; + *proto = pcap_nametoproto(sp->s_proto); + /* + * We need to check /etc/services for ambiguous entries. + * If we find the ambiguous entry, and it has the + * same port number, change the proto to PROTO_UNDEF + * so both TCP and UDP will be checked. + */ + if (*proto == IPPROTO_TCP) + other = "udp"; + else + other = "tcp"; + + sp = getservbyname(name, other); + if (sp != 0) { + NTOHS(sp->s_port); +#ifdef notdef + if (*port != sp->s_port) + /* Can't handle ambiguous names that refer + to different port numbers. */ + warning("ambiguous port %s in /etc/services", + name); +#endif + *proto = PROTO_UNDEF; + } + return 1; + } +#if defined(ultrix) || defined(__osf__) + /* Special hack in case NFS isn't in /etc/services */ + if (strcmp(name, "nfs") == 0) { + *port = 2049; + *proto = PROTO_UNDEF; + return 1; + } +#endif + return 0; +} + +int +pcap_nametoproto(const char *str) +{ + struct protoent *p; + + p = getprotobyname(str); + if (p != 0) + return p->p_proto; + else + return PROTO_UNDEF; +} + +#include "ethertype.h" + +struct eproto { + char *s; + u_short p; +}; + +/* Static data base of ether protocol types. */ +struct eproto eproto_db[] = { + { "pup", ETHERTYPE_PUP }, + { "xns", ETHERTYPE_NS }, + { "ip", ETHERTYPE_IP }, + { "arp", ETHERTYPE_ARP }, + { "rarp", ETHERTYPE_REVARP }, + { "sprite", ETHERTYPE_SPRITE }, + { "mopdl", ETHERTYPE_MOPDL }, + { "moprc", ETHERTYPE_MOPRC }, + { "decnet", ETHERTYPE_DN }, + { "lat", ETHERTYPE_LAT }, + { "lanbridge", ETHERTYPE_LANBRIDGE }, + { "vexp", ETHERTYPE_VEXP }, + { "vprod", ETHERTYPE_VPROD }, + { "atalk", ETHERTYPE_ATALK }, + { "atalkarp", ETHERTYPE_AARP }, + { "loopback", ETHERTYPE_LOOPBACK }, + { "decdts", ETHERTYPE_DECDTS }, + { "decdns", ETHERTYPE_DECDNS }, + { (char *)0, 0 } +}; + +int +pcap_nametoeproto(const char *s) +{ + struct eproto *p = eproto_db; + + while (p->s != 0) { + if (strcmp(p->s, s) == 0) + return p->p; + p += 1; + } + return PROTO_UNDEF; +} + +/* Hex digit to integer. */ +static __inline int +xdtoi(c) + register int c; +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +bpf_u_int32 +__pcap_atoin(const char *s) +{ + bpf_u_int32 addr = 0; + u_int n; + + while (1) { + n = 0; + while (*s && *s != '.') + n = n * 10 + *s++ - '0'; + addr <<= 8; + addr |= n & 0xff; + if (*s == '\0') + return addr; + ++s; + } + /* NOTREACHED */ +} + +bpf_u_int32 +__pcap_atodn(const char *s) +{ +#define AREASHIFT 10 +#define AREAMASK 0176000 +#define NODEMASK 01777 + + bpf_u_int32 addr = 0; + u_int node, area; + + if (sscanf((char *)s, "%d.%d", &area, &node) != 2) + bpf_error("malformed decnet address '%s'", s); + + addr = (area << AREASHIFT) & AREAMASK; + addr |= (node & NODEMASK); + + return(addr); +} + +/* + * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new + * ethernet address. Assumes 's' is well formed. + */ +u_char * +pcap_ether_aton(const char *s) +{ + register u_char *ep, *e; + register u_int d; + + e = ep = (u_char *)malloc(6); + + while (*s) { + if (*s == ':') + s += 1; + d = xdtoi(*s++); + if (isxdigit(*s)) { + d <<= 4; + d |= xdtoi(*s++); + } + *ep++ = d; + } + + return (e); +} + +#ifndef HAVE_ETHER_HOSTTON +/* Roll our own */ +u_char * +pcap_ether_hostton(const char *name) +{ + register struct pcap_etherent *ep; + register u_char *ap; + static FILE *fp = NULL; + static init = 0; + + if (!init) { + fp = fopen(PCAP_ETHERS_FILE, "r"); + ++init; + if (fp == NULL) + return (NULL); + } else if (fp == NULL) + return (NULL); + else + rewind(fp); + + while ((ep = pcap_next_etherent(fp)) != NULL) { + if (strcmp(ep->name, name) == 0) { + ap = (u_char *)malloc(6); + if (ap != NULL) { + memcpy(ap, ep->addr, 6); + return (ap); + } + break; + } + } + return (NULL); +} +#else + +#ifndef sgi +extern int ether_hostton(char *, struct ether_addr *); +#endif + +/* Use the os supplied routines */ +u_char * +pcap_ether_hostton(const char *name) +{ + register u_char *ap; + u_char a[6]; + + ap = NULL; + if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) { + ap = (u_char *)malloc(6); + if (ap != NULL) + memcpy(ap, a, 6); + } + return (ap); +} +#endif + +u_short +__pcap_nametodnaddr(const char *name) +{ +#ifdef DECNETLIB + struct nodeent *getnodebyname(); + struct nodeent *nep; + unsigned short res; + + nep = getnodebyname(name); + if (nep == ((struct nodeent *)0)) + bpf_error("unknown decnet host name '%s'\n", name); + + memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); + return(res); +#else + bpf_error("decnet name support not included, '%s' cannot be translated\n", + name); +#ifdef lint + return 0; +#endif +#endif +} diff --git a/pcap/optimize.c b/pcap/optimize.c new file mode 100644 index 0000000..e78ce1c --- /dev/null +++ b/pcap/optimize.c @@ -0,0 +1,2029 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: optimize.c,v 1.5 1996/09/16 02:33:07 tholo Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Optimization module for tcpdump intermediate representation. + */ +#ifndef lint +static char rcsid[] = + "@(#) Header: optimize.c,v 1.58 96/06/16 22:36:59 leres Exp (LBL)"; +#endif + +#include +#include + +#include + +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" +#include "gencode.h" + +#ifdef BDEBUG +extern int dflag; +#endif + +#define A_ATOM BPF_MEMWORDS +#define X_ATOM (BPF_MEMWORDS+1) + +#define NOP -1 + +/* + * This define is used to represent *both* the accumulator and + * x register in use-def computations. + * Currently, the use-def code assumes only one definition per instruction. + */ +#define AX_ATOM N_ATOMS + +/* + * A flag to indicate that further optimization is needed. + * Iterative passes are continued until a given pass yields no + * branch movement. + */ +static int done; + +/* + * A block is marked if only if its mark equals the current mark. + * Rather than traverse the code array, marking each item, 'cur_mark' is + * incremented. This automatically makes each element unmarked. + */ +static int cur_mark; +#define isMarked(p) ((p)->mark == cur_mark) +#define unMarkAll() cur_mark += 1 +#define Mark(p) ((p)->mark = cur_mark) + +static void opt_init(struct block *); +static void opt_cleanup(void); + +static void make_marks(struct block *); +static void mark_code(struct block *); + +static void intern_blocks(struct block *); + +static int eq_slist(struct slist *, struct slist *); + +static void find_levels_r(struct block *); + +static void find_levels(struct block *); +static void find_dom(struct block *); +static void propedom(struct edge *); +static void find_edom(struct block *); +static void find_closure(struct block *); +static int atomuse(struct stmt *); +static int atomdef(struct stmt *); +static void compute_local_ud(struct block *); +static void find_ud(struct block *); +static void init_val(void); +static int F(int, int, int); +static __inline void vstore(struct stmt *, int *, int, int); +static void opt_blk(struct block *, int); +static int use_conflict(struct block *, struct block *); +static void opt_j(struct edge *); +static void or_pullup(struct block *); +static void and_pullup(struct block *); +static void opt_blks(struct block *, int); +static __inline void link_inedge(struct edge *, struct block *); +static void find_inedges(struct block *); +static void opt_root(struct block **); +static void opt_loop(struct block *, int); +static void fold_op(struct stmt *, int, int); +static __inline struct slist *this_op(struct slist *); +static void opt_not(struct block *); +static void opt_peep(struct block *); +static void opt_stmt(struct stmt *, int[], int); +static void deadstmt(struct stmt *, struct stmt *[]); +static void opt_deadstores(struct block *); +static void opt_blk(struct block *, int); +static int use_conflict(struct block *, struct block *); +static void opt_j(struct edge *); +static struct block *fold_edge(struct block *, struct edge *); +static __inline int eq_blk(struct block *, struct block *); +static int slength(struct slist *); +static int count_blocks(struct block *); +static void number_blks_r(struct block *); +static int count_stmts(struct block *); +static int convert_code_r(struct block *); +#ifdef BDEBUG +static void opt_dump(struct block *); +#endif + +static int n_blocks; +struct block **blocks; +static int n_edges; +struct edge **edges; + +/* + * A bit vector set representation of the dominators. + * We round up the set size to the next power of two. + */ +static int nodewords; +static int edgewords; +struct block **levels; +bpf_u_int32 *space; +#define BITS_PER_WORD (8*sizeof(bpf_u_int32)) +/* + * True if a is in uset {p} + */ +#define SET_MEMBER(p, a) \ +((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD))) + +/* + * Add 'a' to uset p. + */ +#define SET_INSERT(p, a) \ +(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD)) + +/* + * Delete 'a' from uset p. + */ +#define SET_DELETE(p, a) \ +(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD)) + +/* + * a := a intersect b + */ +#define SET_INTERSECT(a, b, n)\ +{\ + register bpf_u_int32 *_x = a, *_y = b;\ + register int _n = n;\ + while (--_n >= 0) *_x++ &= *_y++;\ +} + +/* + * a := a - b + */ +#define SET_SUBTRACT(a, b, n)\ +{\ + register bpf_u_int32 *_x = a, *_y = b;\ + register int _n = n;\ + while (--_n >= 0) *_x++ &=~ *_y++;\ +} + +/* + * a := a union b + */ +#define SET_UNION(a, b, n)\ +{\ + register bpf_u_int32 *_x = a, *_y = b;\ + register int _n = n;\ + while (--_n >= 0) *_x++ |= *_y++;\ +} + +static uset all_dom_sets; +static uset all_closure_sets; +static uset all_edge_sets; + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +static void +find_levels_r(b) + struct block *b; +{ + int level; + + if (isMarked(b)) + return; + + Mark(b); + b->link = 0; + + if (JT(b)) { + find_levels_r(JT(b)); + find_levels_r(JF(b)); + level = MAX(JT(b)->level, JF(b)->level) + 1; + } else + level = 0; + b->level = level; + b->link = levels[level]; + levels[level] = b; +} + +/* + * Level graph. The levels go from 0 at the leaves to + * N_LEVELS at the root. The levels[] array points to the + * first node of the level list, whose elements are linked + * with the 'link' field of the struct block. + */ +static void +find_levels(root) + struct block *root; +{ + memset((char *)levels, 0, n_blocks * sizeof(*levels)); + unMarkAll(); + find_levels_r(root); +} + +/* + * Find dominator relationships. + * Assumes graph has been leveled. + */ +static void +find_dom(root) + struct block *root; +{ + int i; + struct block *b; + bpf_u_int32 *x; + + /* + * Initialize sets to contain all nodes. + */ + x = all_dom_sets; + i = n_blocks * nodewords; + while (--i >= 0) + *x++ = ~0; + /* Root starts off empty. */ + for (i = nodewords; --i >= 0;) + root->dom[i] = 0; + + /* root->level is the highest level no found. */ + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b; b = b->link) { + SET_INSERT(b->dom, b->id); + if (JT(b) == 0) + continue; + SET_INTERSECT(JT(b)->dom, b->dom, nodewords); + SET_INTERSECT(JF(b)->dom, b->dom, nodewords); + } + } +} + +static void +propedom(ep) + struct edge *ep; +{ + SET_INSERT(ep->edom, ep->id); + if (ep->succ) { + SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords); + SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords); + } +} + +/* + * Compute edge dominators. + * Assumes graph has been leveled and predecessors established. + */ +static void +find_edom(root) + struct block *root; +{ + int i; + uset x; + struct block *b; + + x = all_edge_sets; + for (i = n_edges * edgewords; --i >= 0; ) + x[i] = ~0; + + /* root->level is the highest level no found. */ + memset(root->et.edom, 0, edgewords * sizeof(*(uset)0)); + memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0)); + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b != 0; b = b->link) { + propedom(&b->et); + propedom(&b->ef); + } + } +} + +/* + * Find the backwards transitive closure of the flow graph. These sets + * are backwards in the sense that we find the set of nodes that reach + * a given node, not the set of nodes that can be reached by a node. + * + * Assumes graph has been leveled. + */ +static void +find_closure(root) + struct block *root; +{ + int i; + struct block *b; + + /* + * Initialize sets to contain no nodes. + */ + memset((char *)all_closure_sets, 0, + n_blocks * nodewords * sizeof(*all_closure_sets)); + + /* root->level is the highest level no found. */ + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b; b = b->link) { + SET_INSERT(b->closure, b->id); + if (JT(b) == 0) + continue; + SET_UNION(JT(b)->closure, b->closure, nodewords); + SET_UNION(JF(b)->closure, b->closure, nodewords); + } + } +} + +/* + * Return the register number that is used by s. If A and X are both + * used, return AX_ATOM. If no register is used, return -1. + * + * The implementation should probably change to an array access. + */ +static int +atomuse(s) + struct stmt *s; +{ + register int c = s->code; + + if (c == NOP) + return -1; + + switch (BPF_CLASS(c)) { + + case BPF_RET: + return (BPF_RVAL(c) == BPF_A) ? A_ATOM : + (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1; + + case BPF_LD: + case BPF_LDX: + return (BPF_MODE(c) == BPF_IND) ? X_ATOM : + (BPF_MODE(c) == BPF_MEM) ? s->k : -1; + + case BPF_ST: + return A_ATOM; + + case BPF_STX: + return X_ATOM; + + case BPF_JMP: + case BPF_ALU: + if (BPF_SRC(c) == BPF_X) + return AX_ATOM; + return A_ATOM; + + case BPF_MISC: + return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM; + } + abort(); + /* NOTREACHED */ +} + +/* + * Return the register number that is defined by 's'. We assume that + * a single stmt cannot define more than one register. If no register + * is defined, return -1. + * + * The implementation should probably change to an array access. + */ +static int +atomdef(s) + struct stmt *s; +{ + if (s->code == NOP) + return -1; + + switch (BPF_CLASS(s->code)) { + + case BPF_LD: + case BPF_ALU: + return A_ATOM; + + case BPF_LDX: + return X_ATOM; + + case BPF_ST: + case BPF_STX: + return s->k; + + case BPF_MISC: + return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM; + } + return -1; +} + +static void +compute_local_ud(b) + struct block *b; +{ + struct slist *s; + atomset def = 0, use = 0, kill = 0; + int atom; + + for (s = b->stmts; s; s = s->next) { + if (s->s.code == NOP) + continue; + atom = atomuse(&s->s); + if (atom >= 0) { + if (atom == AX_ATOM) { + if (!ATOMELEM(def, X_ATOM)) + use |= ATOMMASK(X_ATOM); + if (!ATOMELEM(def, A_ATOM)) + use |= ATOMMASK(A_ATOM); + } + else if (atom < N_ATOMS) { + if (!ATOMELEM(def, atom)) + use |= ATOMMASK(atom); + } + else + abort(); + } + atom = atomdef(&s->s); + if (atom >= 0) { + if (!ATOMELEM(use, atom)) + kill |= ATOMMASK(atom); + def |= ATOMMASK(atom); + } + } + if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP) + use |= ATOMMASK(A_ATOM); + + b->def = def; + b->kill = kill; + b->in_use = use; +} + +/* + * Assume graph is already leveled. + */ +static void +find_ud(root) + struct block *root; +{ + int i, maxlevel; + struct block *p; + + /* + * root->level is the highest level no found; + * count down from there. + */ + maxlevel = root->level; + for (i = maxlevel; i >= 0; --i) + for (p = levels[i]; p; p = p->link) { + compute_local_ud(p); + p->out_use = 0; + } + + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + p->out_use |= JT(p)->in_use | JF(p)->in_use; + p->in_use |= p->out_use &~ p->kill; + } + } +} + +/* + * These data structures are used in a Cocke and Shwarz style + * value numbering scheme. Since the flowgraph is acyclic, + * exit values can be propagated from a node's predecessors + * provided it is uniquely defined. + */ +struct valnode { + int code; + int v0, v1; + int val; + struct valnode *next; +}; + +#define MODULUS 213 +static struct valnode *hashtbl[MODULUS]; +static int curval; +static int maxval; + +/* Integer constants mapped with the load immediate opcode. */ +#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L) + +struct vmapinfo { + int is_const; + bpf_int32 const_val; +}; + +struct vmapinfo *vmap; +struct valnode *vnode_base; +struct valnode *next_vnode; + +static void +init_val() +{ + curval = 0; + next_vnode = vnode_base; + memset((char *)vmap, 0, maxval * sizeof(*vmap)); + memset((char *)hashtbl, 0, sizeof hashtbl); +} + +/* Because we really don't have an IR, this stuff is a little messy. */ +static int +F(code, v0, v1) + int code; + int v0, v1; +{ + u_int hash; + int val; + struct valnode *p; + + hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8); + hash %= MODULUS; + + for (p = hashtbl[hash]; p; p = p->next) + if (p->code == code && p->v0 == v0 && p->v1 == v1) + return p->val; + + val = ++curval; + if (BPF_MODE(code) == BPF_IMM && + (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) { + vmap[val].const_val = v0; + vmap[val].is_const = 1; + } + p = next_vnode++; + p->val = val; + p->code = code; + p->v0 = v0; + p->v1 = v1; + p->next = hashtbl[hash]; + hashtbl[hash] = p; + + return val; +} + +static __inline void +vstore(s, valp, newval, alter) + struct stmt *s; + int *valp; + int newval; + int alter; +{ + if (alter && *valp == newval) + s->code = NOP; + else + *valp = newval; +} + +static void +fold_op(s, v0, v1) + struct stmt *s; + int v0, v1; +{ + bpf_int32 a, b; + + a = vmap[v0].const_val; + b = vmap[v1].const_val; + + switch (BPF_OP(s->code)) { + case BPF_ADD: + a += b; + break; + + case BPF_SUB: + a -= b; + break; + + case BPF_MUL: + a *= b; + break; + + case BPF_DIV: + if (b == 0) + bpf_error("division by zero"); + a /= b; + break; + + case BPF_AND: + a &= b; + break; + + case BPF_OR: + a |= b; + break; + + case BPF_LSH: + a <<= b; + break; + + case BPF_RSH: + a >>= b; + break; + + case BPF_NEG: + a = -a; + break; + + default: + abort(); + } + s->k = a; + s->code = BPF_LD|BPF_IMM; + done = 0; +} + +static __inline struct slist * +this_op(s) + struct slist *s; +{ + while (s != 0 && s->s.code == NOP) + s = s->next; + return s; +} + +static void +opt_not(b) + struct block *b; +{ + struct block *tmp = JT(b); + + JT(b) = JF(b); + JF(b) = tmp; +} + +static void +opt_peep(b) + struct block *b; +{ + struct slist *s; + struct slist *next, *last; + int val; + + s = b->stmts; + if (s == 0) + return; + + last = s; + while (1) { + s = this_op(s); + if (s == 0) + break; + next = this_op(s->next); + if (next == 0) + break; + last = next; + + /* + * st M[k] --> st M[k] + * ldx M[k] tax + */ + if (s->s.code == BPF_ST && + next->s.code == (BPF_LDX|BPF_MEM) && + s->s.k == next->s.k) { + done = 0; + next->s.code = BPF_MISC|BPF_TAX; + } + /* + * ld #k --> ldx #k + * tax txa + */ + if (s->s.code == (BPF_LD|BPF_IMM) && + next->s.code == (BPF_MISC|BPF_TAX)) { + s->s.code = BPF_LDX|BPF_IMM; + next->s.code = BPF_MISC|BPF_TXA; + done = 0; + } + /* + * This is an ugly special case, but it happens + * when you say tcp[k] or udp[k] where k is a constant. + */ + if (s->s.code == (BPF_LD|BPF_IMM)) { + struct slist *add, *tax, *ild; + + /* + * Check that X isn't used on exit from this + * block (which the optimizer might cause). + * We know the code generator won't generate + * any local dependencies. + */ + if (ATOMELEM(b->out_use, X_ATOM)) + break; + + if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B)) + add = next; + else + add = this_op(next->next); + if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X)) + break; + + tax = this_op(add->next); + if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) + break; + + ild = this_op(tax->next); + if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || + BPF_MODE(ild->s.code) != BPF_IND) + break; + /* + * XXX We need to check that X is not + * subsequently used. We know we can eliminate the + * accumulator modifications since it is defined + * by the last stmt of this sequence. + * + * We want to turn this sequence: + * + * (004) ldi #0x2 {s} + * (005) ldxms [14] {next} -- optional + * (006) addx {add} + * (007) tax {tax} + * (008) ild [x+0] {ild} + * + * into this sequence: + * + * (004) nop + * (005) ldxms [14] + * (006) nop + * (007) nop + * (008) ild [x+2] + * + */ + ild->s.k += s->s.k; + s->s.code = NOP; + add->s.code = NOP; + tax->s.code = NOP; + done = 0; + } + s = next; + } + /* + * If we have a subtract to do a comparison, and the X register + * is a known constant, we can merge this value into the + * comparison. + */ + if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) && + !ATOMELEM(b->out_use, A_ATOM)) { + val = b->val[X_ATOM]; + if (vmap[val].is_const) { + int op; + + b->s.k += vmap[val].const_val; + op = BPF_OP(b->s.code); + if (op == BPF_JGT || op == BPF_JGE) { + struct block *t = JT(b); + JT(b) = JF(b); + JF(b) = t; + b->s.k += 0x80000000; + } + last->s.code = NOP; + done = 0; + } else if (b->s.k == 0) { + /* + * sub x -> nop + * j #0 j x + */ + last->s.code = NOP; + b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) | + BPF_X; + done = 0; + } + } + /* + * Likewise, a constant subtract can be simplified. + */ + else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) && + !ATOMELEM(b->out_use, A_ATOM)) { + int op; + + b->s.k += last->s.k; + last->s.code = NOP; + op = BPF_OP(b->s.code); + if (op == BPF_JGT || op == BPF_JGE) { + struct block *t = JT(b); + JT(b) = JF(b); + JF(b) = t; + b->s.k += 0x80000000; + } + done = 0; + } + /* + * and #k nop + * jeq #0 -> jset #k + */ + if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && + !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) { + b->s.k = last->s.k; + b->s.code = BPF_JMP|BPF_K|BPF_JSET; + last->s.code = NOP; + done = 0; + opt_not(b); + } + /* + * If the accumulator is a known constant, we can compute the + * comparison result. + */ + val = b->val[A_ATOM]; + if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) { + bpf_int32 v = vmap[val].const_val; + switch (BPF_OP(b->s.code)) { + + case BPF_JEQ: + v = v == b->s.k; + break; + + case BPF_JGT: + v = (unsigned)v > b->s.k; + break; + + case BPF_JGE: + v = (unsigned)v >= b->s.k; + break; + + case BPF_JSET: + v &= b->s.k; + break; + + default: + abort(); + } + if (JF(b) != JT(b)) + done = 0; + if (v) + JF(b) = JT(b); + else + JT(b) = JF(b); + } +} + +/* + * Compute the symbolic value of expression of 's', and update + * anything it defines in the value table 'val'. If 'alter' is true, + * do various optimizations. This code would be cleaner if symbolic + * evaluation and code transformations weren't folded together. + */ +static void +opt_stmt(s, val, alter) + struct stmt *s; + int val[]; + int alter; +{ + int op; + int v; + + switch (s->code) { + + case BPF_LD|BPF_ABS|BPF_W: + case BPF_LD|BPF_ABS|BPF_H: + case BPF_LD|BPF_ABS|BPF_B: + v = F(s->code, s->k, 0L); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_IND|BPF_W: + case BPF_LD|BPF_IND|BPF_H: + case BPF_LD|BPF_IND|BPF_B: + v = val[X_ATOM]; + if (alter && vmap[v].is_const) { + s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code); + s->k += vmap[v].const_val; + v = F(s->code, s->k, 0L); + done = 0; + } + else + v = F(s->code, s->k, v); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_LEN: + v = F(s->code, 0L, 0L); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_IMM: + v = K(s->k); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LDX|BPF_IMM: + v = K(s->k); + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_LDX|BPF_MSH|BPF_B: + v = F(s->code, s->k, 0L); + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_ALU|BPF_NEG: + if (alter && vmap[val[A_ATOM]].is_const) { + s->code = BPF_LD|BPF_IMM; + s->k = -vmap[val[A_ATOM]].const_val; + val[A_ATOM] = K(s->k); + } + else + val[A_ATOM] = F(s->code, val[A_ATOM], 0L); + break; + + case BPF_ALU|BPF_ADD|BPF_K: + case BPF_ALU|BPF_SUB|BPF_K: + case BPF_ALU|BPF_MUL|BPF_K: + case BPF_ALU|BPF_DIV|BPF_K: + case BPF_ALU|BPF_AND|BPF_K: + case BPF_ALU|BPF_OR|BPF_K: + case BPF_ALU|BPF_LSH|BPF_K: + case BPF_ALU|BPF_RSH|BPF_K: + op = BPF_OP(s->code); + if (alter) { + if (s->k == 0) { + if (op == BPF_ADD || op == BPF_SUB || + op == BPF_LSH || op == BPF_RSH || + op == BPF_OR) { + s->code = NOP; + break; + } + if (op == BPF_MUL || op == BPF_AND) { + s->code = BPF_LD|BPF_IMM; + val[A_ATOM] = K(s->k); + break; + } + } + if (vmap[val[A_ATOM]].is_const) { + fold_op(s, val[A_ATOM], K(s->k)); + val[A_ATOM] = K(s->k); + break; + } + } + val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); + break; + + case BPF_ALU|BPF_ADD|BPF_X: + case BPF_ALU|BPF_SUB|BPF_X: + case BPF_ALU|BPF_MUL|BPF_X: + case BPF_ALU|BPF_DIV|BPF_X: + case BPF_ALU|BPF_AND|BPF_X: + case BPF_ALU|BPF_OR|BPF_X: + case BPF_ALU|BPF_LSH|BPF_X: + case BPF_ALU|BPF_RSH|BPF_X: + op = BPF_OP(s->code); + if (alter && vmap[val[X_ATOM]].is_const) { + if (vmap[val[A_ATOM]].is_const) { + fold_op(s, val[A_ATOM], val[X_ATOM]); + val[A_ATOM] = K(s->k); + } + else { + s->code = BPF_ALU|BPF_K|op; + s->k = vmap[val[X_ATOM]].const_val; + done = 0; + val[A_ATOM] = + F(s->code, val[A_ATOM], K(s->k)); + } + break; + } + /* + * Check if we're doing something to an accumulator + * that is 0, and simplify. This may not seem like + * much of a simplification but it could open up further + * optimizations. + * XXX We could also check for mul by 1, and -1, etc. + */ + if (alter && vmap[val[A_ATOM]].is_const + && vmap[val[A_ATOM]].const_val == 0) { + if (op == BPF_ADD || op == BPF_OR || + op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) { + s->code = BPF_MISC|BPF_TXA; + vstore(s, &val[A_ATOM], val[X_ATOM], alter); + break; + } + else if (op == BPF_MUL || op == BPF_DIV || + op == BPF_AND) { + s->code = BPF_LD|BPF_IMM; + s->k = 0; + vstore(s, &val[A_ATOM], K(s->k), alter); + break; + } + else if (op == BPF_NEG) { + s->code = NOP; + break; + } + } + val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]); + break; + + case BPF_MISC|BPF_TXA: + vstore(s, &val[A_ATOM], val[X_ATOM], alter); + break; + + case BPF_LD|BPF_MEM: + v = val[s->k]; + if (alter && vmap[v].is_const) { + s->code = BPF_LD|BPF_IMM; + s->k = vmap[v].const_val; + done = 0; + } + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_MISC|BPF_TAX: + vstore(s, &val[X_ATOM], val[A_ATOM], alter); + break; + + case BPF_LDX|BPF_MEM: + v = val[s->k]; + if (alter && vmap[v].is_const) { + s->code = BPF_LDX|BPF_IMM; + s->k = vmap[v].const_val; + done = 0; + } + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_ST: + vstore(s, &val[s->k], val[A_ATOM], alter); + break; + + case BPF_STX: + vstore(s, &val[s->k], val[X_ATOM], alter); + break; + } +} + +static void +deadstmt(s, last) + register struct stmt *s; + register struct stmt *last[]; +{ + register int atom; + + atom = atomuse(s); + if (atom >= 0) { + if (atom == AX_ATOM) { + last[X_ATOM] = 0; + last[A_ATOM] = 0; + } + else + last[atom] = 0; + } + atom = atomdef(s); + if (atom >= 0) { + if (last[atom]) { + done = 0; + last[atom]->code = NOP; + } + last[atom] = s; + } +} + +static void +opt_deadstores(b) + register struct block *b; +{ + register struct slist *s; + register int atom; + struct stmt *last[N_ATOMS]; + + memset((char *)last, 0, sizeof last); + + for (s = b->stmts; s != 0; s = s->next) + deadstmt(&s->s, last); + deadstmt(&b->s, last); + + for (atom = 0; atom < N_ATOMS; ++atom) + if (last[atom] && !ATOMELEM(b->out_use, atom)) { + last[atom]->code = NOP; + done = 0; + } +} + +static void +opt_blk(b, do_stmts) + struct block *b; + int do_stmts; +{ + struct slist *s; + struct edge *p; + int i; + bpf_int32 aval; + + /* + * Initialize the atom values. + * If we have no predecessors, everything is undefined. + * Otherwise, we inherent our values from our predecessors. + * If any register has an ambiguous value (i.e. control paths are + * merging) give it the undefined value of 0. + */ + p = b->in_edges; + if (p == 0) + memset((char *)b->val, 0, sizeof(b->val)); + else { + memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val)); + while ((p = p->next) != NULL) { + for (i = 0; i < N_ATOMS; ++i) + if (b->val[i] != p->pred->val[i]) + b->val[i] = 0; + } + } + aval = b->val[A_ATOM]; + for (s = b->stmts; s; s = s->next) + opt_stmt(&s->s, b->val, do_stmts); + + /* + * This is a special case: if we don't use anything from this + * block, and we load the accumulator with value that is + * already there, or if this block is a return, + * eliminate all the statements. + */ + if (do_stmts && + ((b->out_use == 0 && aval != 0 &&b->val[A_ATOM] == aval) || + BPF_CLASS(b->s.code) == BPF_RET)) { + if (b->stmts != 0) { + b->stmts = 0; + done = 0; + } + } else { + opt_peep(b); + opt_deadstores(b); + } + /* + * Set up values for branch optimizer. + */ + if (BPF_SRC(b->s.code) == BPF_K) + b->oval = K(b->s.k); + else + b->oval = b->val[X_ATOM]; + b->et.code = b->s.code; + b->ef.code = -b->s.code; +} + +/* + * Return true if any register that is used on exit from 'succ', has + * an exit value that is different from the corresponding exit value + * from 'b'. + */ +static int +use_conflict(b, succ) + struct block *b, *succ; +{ + int atom; + atomset use = succ->out_use; + + if (use == 0) + return 0; + + for (atom = 0; atom < N_ATOMS; ++atom) + if (ATOMELEM(use, atom)) + if (b->val[atom] != succ->val[atom]) + return 1; + return 0; +} + +static struct block * +fold_edge(child, ep) + struct block *child; + struct edge *ep; +{ + int sense; + int aval0, aval1, oval0, oval1; + int code = ep->code; + + if (code < 0) { + code = -code; + sense = 0; + } else + sense = 1; + + if (child->s.code != code) + return 0; + + aval0 = child->val[A_ATOM]; + oval0 = child->oval; + aval1 = ep->pred->val[A_ATOM]; + oval1 = ep->pred->oval; + + if (aval0 != aval1) + return 0; + + if (oval0 == oval1) + /* + * The operands are identical, so the + * result is true if a true branch was + * taken to get here, otherwise false. + */ + return sense ? JT(child) : JF(child); + + if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K)) + /* + * At this point, we only know the comparison if we + * came down the true branch, and it was an equality + * comparison with a constant. We rely on the fact that + * distinct constants have distinct value numbers. + */ + return JF(child); + + return 0; +} + +static void +opt_j(ep) + struct edge *ep; +{ + register int i, k; + register struct block *target; + + if (JT(ep->succ) == 0) + return; + + if (JT(ep->succ) == JF(ep->succ)) { + /* + * Common branch targets can be eliminated, provided + * there is no data dependency. + */ + if (!use_conflict(ep->pred, ep->succ->et.succ)) { + done = 0; + ep->succ = JT(ep->succ); + } + } + /* + * For each edge dominator that matches the successor of this + * edge, promote the edge successor to the its grandchild. + * + * XXX We violate the set abstraction here in favor a reasonably + * efficient loop. + */ + top: + for (i = 0; i < edgewords; ++i) { + register bpf_u_int32 x = ep->edom[i]; + + while (x != 0) { + k = ffs(x) - 1; + x &=~ (1 << k); + k += i * BITS_PER_WORD; + + target = fold_edge(ep->succ, edges[k]); + /* + * Check that there is no data dependency between + * nodes that will be violated if we move the edge. + */ + if (target != 0 && !use_conflict(ep->pred, target)) { + done = 0; + ep->succ = target; + if (JT(target) != 0) + /* + * Start over unless we hit a leaf. + */ + goto top; + return; + } + } + } +} + + +static void +or_pullup(b) + struct block *b; +{ + int val, at_top; + struct block *pull; + struct block **diffp, **samep; + struct edge *ep; + + ep = b->in_edges; + if (ep == 0) + return; + + /* + * Make sure each predecessor loads the same value. + * XXX why? + */ + val = ep->pred->val[A_ATOM]; + for (ep = ep->next; ep != 0; ep = ep->next) + if (val != ep->pred->val[A_ATOM]) + return; + + if (JT(b->in_edges->pred) == b) + diffp = &JT(b->in_edges->pred); + else + diffp = &JF(b->in_edges->pred); + + at_top = 1; + while (1) { + if (*diffp == 0) + return; + + if (JT(*diffp) != JT(b)) + return; + + if (!SET_MEMBER((*diffp)->dom, b->id)) + return; + + if ((*diffp)->val[A_ATOM] != val) + break; + + diffp = &JF(*diffp); + at_top = 0; + } + samep = &JF(*diffp); + while (1) { + if (*samep == 0) + return; + + if (JT(*samep) != JT(b)) + return; + + if (!SET_MEMBER((*samep)->dom, b->id)) + return; + + if ((*samep)->val[A_ATOM] == val) + break; + + /* XXX Need to check that there are no data dependencies + between dp0 and dp1. Currently, the code generator + will not produce such dependencies. */ + samep = &JF(*samep); + } +#ifdef notdef + /* XXX This doesn't cover everything. */ + for (i = 0; i < N_ATOMS; ++i) + if ((*samep)->val[i] != pred->val[i]) + return; +#endif + /* Pull up the node. */ + pull = *samep; + *samep = JF(pull); + JF(pull) = *diffp; + + /* + * At the top of the chain, each predecessor needs to point at the + * pulled up node. Inside the chain, there is only one predecessor + * to worry about. + */ + if (at_top) { + for (ep = b->in_edges; ep != 0; ep = ep->next) { + if (JT(ep->pred) == b) + JT(ep->pred) = pull; + else + JF(ep->pred) = pull; + } + } + else + *diffp = pull; + + done = 0; +} + +static void +and_pullup(b) + struct block *b; +{ + int val, at_top; + struct block *pull; + struct block **diffp, **samep; + struct edge *ep; + + ep = b->in_edges; + if (ep == 0) + return; + + /* + * Make sure each predecessor loads the same value. + */ + val = ep->pred->val[A_ATOM]; + for (ep = ep->next; ep != 0; ep = ep->next) + if (val != ep->pred->val[A_ATOM]) + return; + + if (JT(b->in_edges->pred) == b) + diffp = &JT(b->in_edges->pred); + else + diffp = &JF(b->in_edges->pred); + + at_top = 1; + while (1) { + if (*diffp == 0) + return; + + if (JF(*diffp) != JF(b)) + return; + + if (!SET_MEMBER((*diffp)->dom, b->id)) + return; + + if ((*diffp)->val[A_ATOM] != val) + break; + + diffp = &JT(*diffp); + at_top = 0; + } + samep = &JT(*diffp); + while (1) { + if (*samep == 0) + return; + + if (JF(*samep) != JF(b)) + return; + + if (!SET_MEMBER((*samep)->dom, b->id)) + return; + + if ((*samep)->val[A_ATOM] == val) + break; + + /* XXX Need to check that there are no data dependencies + between diffp and samep. Currently, the code generator + will not produce such dependencies. */ + samep = &JT(*samep); + } +#ifdef notdef + /* XXX This doesn't cover everything. */ + for (i = 0; i < N_ATOMS; ++i) + if ((*samep)->val[i] != pred->val[i]) + return; +#endif + /* Pull up the node. */ + pull = *samep; + *samep = JT(pull); + JT(pull) = *diffp; + + /* + * At the top of the chain, each predecessor needs to point at the + * pulled up node. Inside the chain, there is only one predecessor + * to worry about. + */ + if (at_top) { + for (ep = b->in_edges; ep != 0; ep = ep->next) { + if (JT(ep->pred) == b) + JT(ep->pred) = pull; + else + JF(ep->pred) = pull; + } + } + else + *diffp = pull; + + done = 0; +} + +static void +opt_blks(root, do_stmts) + struct block *root; + int do_stmts; +{ + int i, maxlevel; + struct block *p; + + init_val(); + maxlevel = root->level; + for (i = maxlevel; i >= 0; --i) + for (p = levels[i]; p; p = p->link) + opt_blk(p, do_stmts); + + if (do_stmts) + /* + * No point trying to move branches; it can't possibly + * make a difference at this point. + */ + return; + + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + opt_j(&p->et); + opt_j(&p->ef); + } + } + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + or_pullup(p); + and_pullup(p); + } + } +} + +static __inline void +link_inedge(parent, child) + struct edge *parent; + struct block *child; +{ + parent->next = child->in_edges; + child->in_edges = parent; +} + +static void +find_inedges(root) + struct block *root; +{ + int i; + struct block *b; + + for (i = 0; i < n_blocks; ++i) + blocks[i]->in_edges = 0; + + /* + * Traverse the graph, adding each edge to the predecessor + * list of its successors. Skip the leaves (i.e. level 0). + */ + for (i = root->level; i > 0; --i) { + for (b = levels[i]; b != 0; b = b->link) { + link_inedge(&b->et, JT(b)); + link_inedge(&b->ef, JF(b)); + } + } +} + +static void +opt_root(b) + struct block **b; +{ + struct slist *tmp, *s; + + s = (*b)->stmts; + (*b)->stmts = 0; + while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b)) + *b = JT(*b); + + tmp = (*b)->stmts; + if (tmp != 0) + sappend(s, tmp); + (*b)->stmts = s; + + /* + * If the root node is a return, then there is no + * point executing any statements (since the bpf machine + * has no side effects). + */ + if (BPF_CLASS((*b)->s.code) == BPF_RET) + (*b)->stmts = 0; +} + +static void +opt_loop(root, do_stmts) + struct block *root; + int do_stmts; +{ + +#ifdef BDEBUG + if (dflag > 1) + opt_dump(root); +#endif + do { + done = 1; + find_levels(root); + find_dom(root); + find_closure(root); + find_inedges(root); + find_ud(root); + find_edom(root); + opt_blks(root, do_stmts); +#ifdef BDEBUG + if (dflag > 1) + opt_dump(root); +#endif + } while (!done); +} + +/* + * Optimize the filter code in its dag representation. + */ +void +bpf_optimize(rootp) + struct block **rootp; +{ + struct block *root; + + root = *rootp; + + opt_init(root); + opt_loop(root, 0); + opt_loop(root, 1); + intern_blocks(root); + opt_root(rootp); + opt_cleanup(); +} + +static void +make_marks(p) + struct block *p; +{ + if (!isMarked(p)) { + Mark(p); + if (BPF_CLASS(p->s.code) != BPF_RET) { + make_marks(JT(p)); + make_marks(JF(p)); + } + } +} + +/* + * Mark code array such that isMarked(i) is true + * only for nodes that are alive. + */ +static void +mark_code(p) + struct block *p; +{ + cur_mark += 1; + make_marks(p); +} + +/* + * True iff the two stmt lists load the same value from the packet into + * the accumulator. + */ +static int +eq_slist(x, y) + struct slist *x, *y; +{ + while (1) { + while (x && x->s.code == NOP) + x = x->next; + while (y && y->s.code == NOP) + y = y->next; + if (x == 0) + return y == 0; + if (y == 0) + return x == 0; + if (x->s.code != y->s.code || x->s.k != y->s.k) + return 0; + x = x->next; + y = y->next; + } +} + +static __inline int +eq_blk(b0, b1) + struct block *b0, *b1; +{ + if (b0->s.code == b1->s.code && + b0->s.k == b1->s.k && + b0->et.succ == b1->et.succ && + b0->ef.succ == b1->ef.succ) + return eq_slist(b0->stmts, b1->stmts); + return 0; +} + +static void +intern_blocks(root) + struct block *root; +{ + struct block *p; + int i, j; + int done; + top: + done = 1; + for (i = 0; i < n_blocks; ++i) + blocks[i]->link = 0; + + mark_code(root); + + for (i = n_blocks - 1; --i >= 0; ) { + if (!isMarked(blocks[i])) + continue; + for (j = i + 1; j < n_blocks; ++j) { + if (!isMarked(blocks[j])) + continue; + if (eq_blk(blocks[i], blocks[j])) { + blocks[i]->link = blocks[j]->link ? + blocks[j]->link : blocks[j]; + break; + } + } + } + for (i = 0; i < n_blocks; ++i) { + p = blocks[i]; + if (JT(p) == 0) + continue; + if (JT(p)->link) { + done = 0; + JT(p) = JT(p)->link; + } + if (JF(p)->link) { + done = 0; + JF(p) = JF(p)->link; + } + } + if (!done) + goto top; +} + +static void +opt_cleanup() +{ + free((void *)vnode_base); + free((void *)vmap); + free((void *)edges); + free((void *)space); + free((void *)levels); + free((void *)blocks); +} + +/* + * Return the number of stmts in 's'. + */ +static int +slength(s) + struct slist *s; +{ + int n = 0; + + for (; s; s = s->next) + if (s->s.code != NOP) + ++n; + return n; +} + +/* + * Return the number of nodes reachable by 'p'. + * All nodes should be initially unmarked. + */ +static int +count_blocks(p) + struct block *p; +{ + if (p == 0 || isMarked(p)) + return 0; + Mark(p); + return count_blocks(JT(p)) + count_blocks(JF(p)) + 1; +} + +/* + * Do a depth first search on the flow graph, numbering the + * the basic blocks, and entering them into the 'blocks' array.` + */ +static void +number_blks_r(p) + struct block *p; +{ + int n; + + if (p == 0 || isMarked(p)) + return; + + Mark(p); + n = n_blocks++; + p->id = n; + blocks[n] = p; + + number_blks_r(JT(p)); + number_blks_r(JF(p)); +} + +/* + * Return the number of stmts in the flowgraph reachable by 'p'. + * The nodes should be unmarked before calling. + */ +static int +count_stmts(p) + struct block *p; +{ + int n; + + if (p == 0 || isMarked(p)) + return 0; + Mark(p); + n = count_stmts(JT(p)) + count_stmts(JF(p)); + return slength(p->stmts) + n + 1; +} + +/* + * Allocate memory. All allocation is done before optimization + * is begun. A linear bound on the size of all data structures is computed + * from the total number of blocks and/or statements. + */ +static void +opt_init(root) + struct block *root; +{ + bpf_u_int32 *p; + int i, n, max_stmts; + + /* + * First, count the blocks, so we can malloc an array to map + * block number to block. Then, put the blocks into the array. + */ + unMarkAll(); + n = count_blocks(root); + blocks = (struct block **)malloc(n * sizeof(*blocks)); + unMarkAll(); + n_blocks = 0; + number_blks_r(root); + + n_edges = 2 * n_blocks; + edges = (struct edge **)malloc(n_edges * sizeof(*edges)); + + /* + * The number of levels is bounded by the number of nodes. + */ + levels = (struct block **)malloc(n_blocks * sizeof(*levels)); + + edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1; + nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1; + + /* XXX */ + space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space) + + n_edges * edgewords * sizeof(*space)); + p = space; + all_dom_sets = p; + for (i = 0; i < n; ++i) { + blocks[i]->dom = p; + p += nodewords; + } + all_closure_sets = p; + for (i = 0; i < n; ++i) { + blocks[i]->closure = p; + p += nodewords; + } + all_edge_sets = p; + for (i = 0; i < n; ++i) { + register struct block *b = blocks[i]; + + b->et.edom = p; + p += edgewords; + b->ef.edom = p; + p += edgewords; + b->et.id = i; + edges[i] = &b->et; + b->ef.id = n_blocks + i; + edges[n_blocks + i] = &b->ef; + b->et.pred = b; + b->ef.pred = b; + } + max_stmts = 0; + for (i = 0; i < n; ++i) + max_stmts += slength(blocks[i]->stmts) + 1; + /* + * We allocate at most 3 value numbers per statement, + * so this is an upper bound on the number of valnodes + * we'll need. + */ + maxval = 3 * max_stmts; + vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap)); + vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap)); +} + +/* + * Some pointers used to convert the basic block form of the code, + * into the array form that BPF requires. 'fstart' will point to + * the malloc'd array while 'ftail' is used during the recursive traversal. + */ +static struct bpf_insn *fstart; +static struct bpf_insn *ftail; + +#ifdef BDEBUG +int bids[1000]; +#endif + +/* + * Returns true if successful. Returns false if a branch has + * an offset that is too large. If so, we have marked that + * branch so that on a subsequent iteration, it will be treated + * properly. + */ +static int +convert_code_r(p) + struct block *p; +{ + struct bpf_insn *dst; + struct slist *src; + int slen; + u_int off; + int extrajmps; /* number of extra jumps inserted */ + + if (p == 0 || isMarked(p)) + return (1); + Mark(p); + + if (convert_code_r(JF(p)) == 0) + return (0); + if (convert_code_r(JT(p)) == 0) + return (0); + + slen = slength(p->stmts); + dst = ftail -= (slen + 1 + p->longjt + p->longjf); + /* inflate length by any extra jumps */ + + p->offset = dst - fstart; + + for (src = p->stmts; src; src = src->next) { + if (src->s.code == NOP) + continue; + dst->code = (u_short)src->s.code; + dst->k = src->s.k; + ++dst; + } +#ifdef BDEBUG + bids[dst - fstart] = p->id + 1; +#endif + dst->code = (u_short)p->s.code; + dst->k = p->s.k; + if (JT(p)) { + extrajmps = 0; + off = JT(p)->offset - (p->offset + slen) - 1; + if (off >= 256) { + /* offset too large for branch, must add a jump */ + if (p->longjt == 0) { + /* mark this instruction and retry */ + p->longjt++; + return(0); + } + /* branch if T to following jump */ + dst->jt = extrajmps; + extrajmps++; + dst[extrajmps].code = BPF_JMP|BPF_JA; + dst[extrajmps].k = off - extrajmps; + } + else + dst->jt = off; + off = JF(p)->offset - (p->offset + slen) - 1; + if (off >= 256) { + /* offset too large for branch, must add a jump */ + if (p->longjf == 0) { + /* mark this instruction and retry */ + p->longjf++; + return(0); + } + /* branch if F to following jump */ + /* if two jumps are inserted, F goes to second one */ + dst->jf = extrajmps; + extrajmps++; + dst[extrajmps].code = BPF_JMP|BPF_JA; + dst[extrajmps].k = off - extrajmps; + } + else + dst->jf = off; + } + return (1); +} + + +/* + * Convert flowgraph intermediate representation to the + * BPF array representation. Set *lenp to the number of instructions. + */ +struct bpf_insn * +icode_to_fcode(root, lenp) + struct block *root; + int *lenp; +{ + int n; + struct bpf_insn *fp; + + /* + * Loop doing convert_codr_r() until no branches remain + * with too-large offsets. + */ + while (1) { + unMarkAll(); + n = *lenp = count_stmts(root); + + fp = (struct bpf_insn *)malloc(sizeof(*fp) * n); + memset((char *)fp, 0, sizeof(*fp) * n); + fstart = fp; + ftail = fp + n; + + unMarkAll(); + if (convert_code_r(root)) + break; + free(fp); + } + + return fp; +} + +#ifdef BDEBUG +static void +opt_dump(root) + struct block *root; +{ + struct bpf_program f; + + memset(bids, 0, sizeof bids); + f.bf_insns = icode_to_fcode(root, &f.bf_len); + bpf_dump(&f, 1); + putchar('\n'); + free((char *)f.bf_insns); +} +#endif diff --git a/pcap/pcap-bpf.c b/pcap/pcap-bpf.c new file mode 100644 index 0000000..c327b55 --- /dev/null +++ b/pcap/pcap-bpf.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: pcap-bpf.c,v 1.7 1996/09/16 02:33:08 tholo Exp $ */ + +/* + * Copyright (c) 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#)Header: pcap-bpf.c,v 1.25 96/06/24 02:50:11 leres Exp (LBL)"; +#endif + +#include /* optionally get BSD define */ +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + struct bpf_stat s; + + if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { + sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno)); + return (-1); + } + + ps->ps_recv = s.bs_recv; + ps->ps_drop = s.bs_drop; + return (0); +} + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + int cc; + int n = 0; + register u_char *bp, *ep; + + again: + cc = p->cc; + if (p->cc == 0) { + cc = read(p->fd, (char *)p->buffer, p->bufsize); + if (cc < 0) { + /* Don't choke when we get ptraced */ + switch (errno) { + + case EINTR: + goto again; + + case EWOULDBLOCK: + return (0); +#if defined(sun) && !defined(BSD) + /* + * Due to a SunOS bug, after 2^31 bytes, the kernel + * file offset overflows and read fails with EINVAL. + * The lseek() to 0 will fix things. + */ + case EINVAL: + if (lseek(p->fd, 0L, SEEK_CUR) + + p->bufsize < 0) { + (void)lseek(p->fd, 0L, SEEK_SET); + goto again; + } + /* fall through */ +#endif + } + sprintf(p->errbuf, "read: %s", pcap_strerror(errno)); + return (-1); + } + bp = p->buffer; + } else + bp = p->bp; + + /* + * Loop through each packet. + */ +#define bhp ((struct bpf_hdr *)bp) + ep = bp + cc; + while (bp < ep) { + register int caplen, hdrlen; + caplen = bhp->bh_caplen; + hdrlen = bhp->bh_hdrlen; + /* + * XXX A bpf_hdr matches a pcap_pkthdr. + */ + (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); + bp += BPF_WORDALIGN(caplen + hdrlen); + if (++n >= cnt && cnt > 0) { + p->bp = bp; + p->cc = ep - bp; + return (n); + } + } +#undef bhp + p->cc = 0; + return (n); +} + +int +pcap_inject(pcap_t *p, const void *buf, size_t len) +{ + return (write(p->fd, buf, len)); +} + +static __inline int +bpf_open(pcap_t *p, char *errbuf) +{ + int fd; + int n = 0; + char device[sizeof "/dev/bpf000"]; + + /* + * Go through all the minors and find one that isn't in use. + */ + do { + (void)sprintf(device, "/dev/bpf%d", n++); + fd = open(device, O_RDONLY); + } while (fd < 0 && errno == EBUSY); + + /* + * XXX better message for all minors used + */ + if (fd < 0) + sprintf(errbuf, "%s: %s", device, pcap_strerror(errno)); + + return (fd); +} + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + int fd; + struct ifreq ifr; + struct bpf_version bv; + u_int v; + pcap_t *p; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); + return (NULL); + } + bzero(p, sizeof(*p)); + fd = bpf_open(p, ebuf); + if (fd < 0) + goto bad; + + p->fd = fd; + p->snapshot = snaplen; + + if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { + sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno)); + goto bad; + } + if (bv.bv_major != BPF_MAJOR_VERSION || + bv.bv_minor < BPF_MINOR_VERSION) { + sprintf(ebuf, "kernel bpf filter out of date"); + goto bad; + } + (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { + sprintf(ebuf, "%s: %s", device, pcap_strerror(errno)); + goto bad; + } + /* Get the data link layer type. */ + if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { + sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno)); + goto bad; + } + p->linktype = v; + + /* set timeout */ + if (to_ms != 0) { + struct timeval to; + to.tv_sec = to_ms / 1000; + to.tv_usec = (to_ms * 1000) % 1000000; + if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { + sprintf(ebuf, "BIOCSRTIMEOUT: %s", + pcap_strerror(errno)); + goto bad; + } + } + if (promisc) + /* set promiscuous mode, okay if it fails */ + (void)ioctl(p->fd, BIOCPROMISC, NULL); + + if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { + sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno)); + goto bad; + } + p->bufsize = v; + p->buffer = (u_char *)malloc(p->bufsize); + if (p->buffer == NULL) { + sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); + goto bad; + } + + return (p); + bad: + (void)close(fd); + free(p); + return (NULL); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + if (p->sf.rfile != NULL) + p->fcode = *fp; + else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { + sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno)); + return (-1); + } + return (0); +} diff --git a/pcap/pcap-int.h b/pcap/pcap-int.h new file mode 100644 index 0000000..9513df1 --- /dev/null +++ b/pcap/pcap-int.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: pcap-int.h,v 1.6 1996/08/03 12:38:44 niklas Exp $ */ + +/* + * Copyright (c) 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: pcap-int.h,v 1.14 95/10/21 22:04:49 leres Exp (LBL) + */ + +#ifndef pcap_int_h +#define pcap_int_h + +#include + +/* + * Savefile + */ +struct pcap_sf { + FILE *rfile; + int swapped; + int version_major; + int version_minor; + u_char *base; +}; + +struct pcap_md { + struct pcap_stat stat; + /*XXX*/ + int use_bpf; + u_long TotPkts; /* can't oflow for 79 hrs on ether */ + u_long TotAccepted; /* count accepted by filter */ + u_long TotDrops; /* count of dropped packets */ + long TotMissed; /* missed by i/f during this run */ + long OrigMissed; /* missed by i/f before this run */ +}; + +struct pcap { + int fd; + int snapshot; + int linktype; + int tzoff; /* timezone offset */ + + struct pcap_sf sf; + struct pcap_md md; + + /* + * Read buffer. + */ + int bufsize; + u_char *buffer; + u_char *bp; + int cc; + + /* + * Place holder for pcap_next(). + */ + u_char *pkt; + + + /* + * Placeholder for filter code if bpf not in kernel. + */ + struct bpf_program fcode; + + char errbuf[PCAP_ERRBUF_SIZE]; +}; + +int yylex(void); + +/* XXX should these be in pcap.h? */ +int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); +int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); + +/* Ultrix pads to make everything line up on a nice boundary */ +#if defined(ultrix) || defined(__alpha) +#define PCAP_FDDIPAD 3 +#endif +#endif diff --git a/pcap/pcap-namedb.h b/pcap/pcap-namedb.h new file mode 100644 index 0000000..d8bf162 --- /dev/null +++ b/pcap/pcap-namedb.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: pcap-namedb.h,v 1.4 1996/07/12 13:19:11 mickey Exp $ */ + +/* + * Copyright (c) 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: pcap-namedb.h,v 1.4 96/06/23 02:21:08 leres Exp (LBL) + */ + +#ifndef lib_pcap_ethers_h +#define lib_pcap_ethers_h + +/* + * As returned by the pcap_next_etherent() + * XXX this stuff doesn't belong in this interface, but this + * library already must do name to address translation, so + * on systems that don't have support for /etc/ethers, we + * export these hooks since they'll + */ +struct pcap_etherent { + u_char addr[6]; + char name[122]; +}; +#ifndef PCAP_ETHERS_FILE +#define PCAP_ETHERS_FILE "/etc/ethers" +#endif +struct pcap_etherent *pcap_next_etherent(FILE *); +u_char *pcap_ether_hostton(const char*); +u_char *pcap_ether_aton(const char *); + +bpf_u_int32 **pcap_nametoaddr(const char *); +bpf_u_int32 pcap_nametonetaddr(const char *); + +int pcap_nametoport(const char *, int *, int *); +int pcap_nametoproto(const char *); +int pcap_nametoeproto(const char *); +/* + * If a protocol is unknown, PROTO_UNDEF is returned. + * Also, pcap_nametoport() returns the protocol along with the port number. + * If there are ambiguous entried in /etc/services (i.e. domain + * can be either tcp or udp) PROTO_UNDEF is returned. + */ +#define PROTO_UNDEF -1 + +/* XXX move these to pcap-int.h? */ +bpf_u_int32 __pcap_atodn(const char *); +bpf_u_int32 __pcap_atoin(const char *); +u_short __pcap_nametodnaddr(const char *); + +#endif diff --git a/pcap/pcap.c b/pcap/pcap.c new file mode 100644 index 0000000..c34b0b2 --- /dev/null +++ b/pcap/pcap.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: pcap.c,v 1.4 1996/07/12 13:19:12 mickey Exp $ */ + +/* + * Copyright (c) 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) Header: pcap.c,v 1.25 96/06/05 21:45:26 leres Exp (LBL)"; +#endif + +#include + +#include +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +int +pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + register int cc; + + if (p->sf.rfile != NULL) + return (pcap_offline_read(p, cnt, callback, user)); + /* XXX keep reading until we get something (or an error occurs) */ + do { + cc = pcap_read(p, cnt, callback, user); + } while (cc == 0); + return (cc); +} + +int +pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + for (;;) { + int n = pcap_dispatch(p, cnt, callback, user); + if (n <= 0) + return (n); + if (cnt > 0) { + cnt -= n; + if (cnt <= 0) + return (0); + } + } +} + +struct singleton { + struct pcap_pkthdr *hdr; + const u_char *pkt; +}; + + +static void +pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) +{ + struct singleton *sp = (struct singleton *)userData; + *sp->hdr = *h; + sp->pkt = pkt; +} + +const u_char * +pcap_next(pcap_t *p, struct pcap_pkthdr *h) +{ + struct singleton s; + + s.hdr = h; + if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0) + return (0); + return (s.pkt); +} + +int +pcap_datalink(pcap_t *p) +{ + return (p->linktype); +} + +int +pcap_snapshot(pcap_t *p) +{ + return (p->snapshot); +} + +int +pcap_is_swapped(pcap_t *p) +{ + return (p->sf.swapped); +} + +int +pcap_major_version(pcap_t *p) +{ + return (p->sf.version_major); +} + +int +pcap_minor_version(pcap_t *p) +{ + return (p->sf.version_minor); +} + +FILE * +pcap_file(pcap_t *p) +{ + return (p->sf.rfile); +} + +int +pcap_fileno(pcap_t *p) +{ + return (p->fd); +} + +void +pcap_perror(pcap_t *p, char *prefix) +{ + fprintf(stderr, "%s: %s\n", prefix, p->errbuf); +} + +char * +pcap_geterr(pcap_t *p) +{ + return (p->errbuf); +} + +/* + * Not all systems have strerror(). + */ +char * +pcap_strerror(int errnum) +{ +#ifdef HAVE_STRERROR + return (strerror(errnum)); +#else + extern int sys_nerr; + extern const char *const sys_errlist[]; + static char ebuf[20]; + + if ((unsigned int)errnum < sys_nerr) + return ((char *)sys_errlist[errnum]); + (void)sprintf(ebuf, "Unknown error: %d", errnum); + return(ebuf); +#endif +} + +void +pcap_close(pcap_t *p) +{ + /*XXX*/ + if (p->fd >= 0) + close(p->fd); + if (p->sf.rfile != NULL) { + (void)fclose(p->sf.rfile); + if (p->sf.base != NULL) + free(p->sf.base); + } else if (p->buffer != NULL) + free(p->buffer); + + free(p); +} diff --git a/pcap/pcap.h b/pcap/pcap.h new file mode 100644 index 0000000..46db423 --- /dev/null +++ b/pcap/pcap.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: pcap.h,v 1.6 1996/07/12 13:19:12 mickey Exp $ */ + +/* + * Copyright (c) 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) Header: pcap.h,v 1.19 96/06/16 22:36:28 leres Exp (LBL) + */ + +#ifndef lib_pcap_h +#define lib_pcap_h + +#include +#include + +#include + +#include + +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 + +#define PCAP_ERRBUF_SIZE 256 + +/* + * Compatibility for systems that have a bpf.h that + * predates the bpf typedefs for 64-bit support. + */ +#if BPF_RELEASE - 0 < 199406 +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +typedef struct pcap pcap_t; +typedef struct pcap_dumper pcap_dumper_t; + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are 32 bit ints so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + */ +struct pcap_file_header { + bpf_u_int32 magic; + u_short version_major; + u_short version_minor; + bpf_int32 thiszone; /* gmt to local correction */ + bpf_u_int32 sigfigs; /* accuracy of timestamps */ + bpf_u_int32 snaplen; /* max length saved portion of each pkt */ + bpf_u_int32 linktype; /* data link type (DLT_*) */ +}; + +/* + * Each packet in the dump file is prepended with this generic header. + * This gets around the problem of different headers for different + * packet interfaces. + */ +struct pcap_pkthdr { + struct timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + +/* + * As returned by the pcap_stats() + */ +struct pcap_stat { + u_int ps_recv; /* number of packets received */ + u_int ps_drop; /* number of packets dropped */ + u_int ps_ifdrop; /* drops by interface XXX not yet supported */ +}; + +typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, + const u_char *); + +char *pcap_lookupdev(char *); +int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *); +pcap_t *pcap_open_live(char *, int, int, int, char *); +pcap_t *pcap_open_offline(char *, char *); +void pcap_close(pcap_t *); +int pcap_loop(pcap_t *, int, pcap_handler, u_char *); +int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); +const u_char* + pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_stats(pcap_t *, struct pcap_stat *); +int pcap_setfilter(pcap_t *, struct bpf_program *); +void pcap_perror(pcap_t *, char *); +char *pcap_strerror(int); +char *pcap_geterr(pcap_t *); +int pcap_compile(pcap_t *, struct bpf_program *, char *, int, + bpf_u_int32); +/* XXX */ +int pcap_freecode(pcap_t *, struct bpf_program *); +int pcap_datalink(pcap_t *); +int pcap_snapshot(pcap_t *); +int pcap_is_swapped(pcap_t *); +int pcap_major_version(pcap_t *); +int pcap_minor_version(pcap_t *); + +/* XXX */ +FILE *pcap_file(pcap_t *); +int pcap_fileno(pcap_t *); + +pcap_dumper_t *pcap_dump_open(pcap_t *, char *); +void pcap_dump_close(pcap_dumper_t *); +void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); + +/* XXX this guy lives in the bpf tree */ +u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +char *bpf_image(struct bpf_insn *, int); + +/* XXX */ +extern int pcap_fddipad; + +#endif diff --git a/pcap/savefile.c b/pcap/savefile.c new file mode 100644 index 0000000..ba1e9c0 --- /dev/null +++ b/pcap/savefile.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: savefile.c,v 1.4 1996/07/12 13:19:13 mickey Exp $ */ + +/* + * Copyright (c) 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static char rcsid[] = + "@(#)Header: savefile.c,v 1.28 95/10/07 03:09:06 leres Exp (LBL)"; +#endif + +/* + * savefile.c - supports offline use of tcpdump + * Extraction/creation by Jeffrey Mogul, DECWRL + * Modified by Steve McCanne, LBL. + * + * Used to save the received packet headers, after filtering, to + * a file, and then read them later. + * The first record in the file contains saved values for the machine + * dependent values so we can print the dump file on any architecture. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +#define TCPDUMP_MAGIC 0xa1b2c3d4 + +/* + * We use the "receiver-makes-right" approach to byte order, + * because time is at a premium when we are writing the file. + * In other words, the pcap_file_header and pcap_pkthdr, + * records are written in host byte order. + * Note that the packets are always written in network byte order. + * + * ntoh[ls] aren't sufficient because we might need to swap on a big-endian + * machine (if the file was written in little-end order). + */ +#define SWAPLONG(y) \ +((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ + ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) + +#define SFERR_TRUNC 1 +#define SFERR_BADVERSION 2 +#define SFERR_BADF 3 +#define SFERR_EOF 4 /* not really an error, just a status */ + +static int +sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen) +{ + struct pcap_file_header hdr; + + hdr.magic = TCPDUMP_MAGIC; + hdr.version_major = PCAP_VERSION_MAJOR; + hdr.version_minor = PCAP_VERSION_MINOR; + + hdr.thiszone = thiszone; + hdr.snaplen = snaplen; + hdr.sigfigs = 0; + hdr.linktype = linktype; + + if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) + return (-1); + + return (0); +} + +static void +swap_hdr(struct pcap_file_header *hp) +{ + hp->version_major = SWAPSHORT(hp->version_major); + hp->version_minor = SWAPSHORT(hp->version_minor); + hp->thiszone = SWAPLONG(hp->thiszone); + hp->sigfigs = SWAPLONG(hp->sigfigs); + hp->snaplen = SWAPLONG(hp->snaplen); + hp->linktype = SWAPLONG(hp->linktype); +} + +pcap_t * +pcap_open_offline(char *fname, char *errbuf) +{ + register pcap_t *p; + register FILE *fp; + struct pcap_file_header hdr; + int linklen; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + strcpy(errbuf, "out of swap"); + return (NULL); + } + + memset((char *)p, 0, sizeof(*p)); + /* + * Set this field so we don't close stdin in pcap_close! + */ + p->fd = -1; + + if (fname[0] == '-' && fname[1] == '\0') + fp = stdin; + else { + fp = fopen(fname, "r"); + if (fp == NULL) { + sprintf(errbuf, "%s: %s", fname, pcap_strerror(errno)); + goto bad; + } + } + if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { + sprintf(errbuf, "fread: %s", pcap_strerror(errno)); + goto bad; + } + if (hdr.magic != TCPDUMP_MAGIC) { + if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) { + sprintf(errbuf, "bad dump file format"); + goto bad; + } + p->sf.swapped = 1; + swap_hdr(&hdr); + } + if (hdr.version_major < PCAP_VERSION_MAJOR) { + sprintf(errbuf, "archaic file format"); + goto bad; + } + p->tzoff = hdr.thiszone; + p->snapshot = hdr.snaplen; + p->linktype = hdr.linktype; + p->sf.rfile = fp; + p->bufsize = hdr.snaplen; + + /* Align link header as required for proper data alignment */ + /* XXX should handle all types */ + switch (p->linktype) { + + case DLT_EN10MB: + linklen = 14; + break; + + case DLT_FDDI: + linklen = 13 + 8; /* fddi_header + llc */ + break; + + case DLT_NULL: + default: + linklen = 0; + break; + } + + p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT); + p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT); + p->sf.version_major = hdr.version_major; + p->sf.version_minor = hdr.version_minor; + + return (p); + bad: + free(p); + return (NULL); +} + +/* + * Read sf_readfile and return the next packet. Return the header in hdr + * and the contents in buf. Return 0 on success, SFERR_EOF if there were + * no more packets, and SFERR_TRUNC if a partial packet was encountered. + */ +static int +sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen) +{ + FILE *fp = p->sf.rfile; + + /* read the stamp */ + if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) { + /* probably an EOF, though could be a truncated packet */ + return (1); + } + + if (p->sf.swapped) { + /* these were written in opposite byte order */ + hdr->caplen = SWAPLONG(hdr->caplen); + hdr->len = SWAPLONG(hdr->len); + hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec); + hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec); + } + /* + * We interchanged the caplen and len fields at version 2.3, + * in order to match the bpf header layout. But unfortunately + * some files were written with version 2.3 in their headers + * but without the interchanged fields. + */ + if (p->sf.version_minor < 3 || + (p->sf.version_minor == 3 && hdr->caplen > hdr->len)) { + int t = hdr->caplen; + hdr->caplen = hdr->len; + hdr->len = t; + } + + if (hdr->caplen > buflen) { + /* + * This can happen due to Solaris 2.3 systems tripping + * over the BUFMOD problem and not setting the snapshot + * correctly in the savefile header. If the caplen isn't + * grossly wrong, try to salvage. + */ + static u_char *tp = NULL; + static int tsize = 0; + + if (tsize < hdr->caplen) { + tsize = ((hdr->caplen + 1023) / 1024) * 1024; + if (tp != NULL) + free((u_char *)tp); + tp = (u_char *)malloc(tsize); + if (tp == NULL) { + sprintf(p->errbuf, "BUFMOD hack malloc"); + return (-1); + } + } + if (fread((char *)tp, hdr->caplen, 1, fp) != 1) { + sprintf(p->errbuf, "truncated dump file"); + return (-1); + } + memcpy((char *)buf, (char *)tp, buflen); + + } else { + /* read the packet itself */ + + if (fread((char *)buf, hdr->caplen, 1, fp) != 1) { + sprintf(p->errbuf, "truncated dump file"); + return (-1); + } + } + return (0); +} + +/* + * Print out packets stored in the file initialized by sf_read_init(). + * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. + */ +int +pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + struct bpf_insn *fcode = p->fcode.bf_insns; + int status = 0; + int n = 0; + + while (status == 0) { + struct pcap_pkthdr h; + + status = sf_next_packet(p, &h, p->buffer, p->bufsize); + if (status) { + if (status == 1) + return (0); + return (status); + } + + if (fcode == NULL || + bpf_filter(fcode, p->buffer, h.len, h.caplen)) { + (*callback)(user, &h, p->buffer); + if (++n >= cnt && cnt > 0) + break; + } + } + /*XXX this breaks semantics tcpslice expects */ + return (n); +} + +/* + * Output a packet to the initialized dump file. + */ +void +pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +{ + register FILE *f; + + f = (FILE *)user; + /* XXX we should check the return status */ + (void)fwrite((char *)h, sizeof(*h), 1, f); + (void)fwrite((char *)sp, h->caplen, 1, f); +} + +/* + * Initialize so that sf_write() will output to the file named 'fname'. + */ +pcap_dumper_t * +pcap_dump_open(pcap_t *p, char *fname) +{ + FILE *f; + if (fname[0] == '-' && fname[1] == '\0') + f = stdout; + else { + f = fopen(fname, "w"); + if (f == NULL) { + sprintf(p->errbuf, "%s: %s", + fname, pcap_strerror(errno)); + return (NULL); + } + } + (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot); + return ((pcap_dumper_t *)f); +} + +void +pcap_dump_close(pcap_dumper_t *p) +{ + +#ifdef notyet + if (ferror((FILE *)p)) + return-an-error; + /* XXX should check return from fclose() too */ +#endif + (void)fclose((FILE *)p); +} diff --git a/pcap/scanner.l b/pcap/scanner.l new file mode 100644 index 0000000..2cbb693 --- /dev/null +++ b/pcap/scanner.l @@ -0,0 +1,198 @@ +%{ +/* $OpenBSD: scanner.l,v 1.5 1996/07/12 13:19:13 mickey Exp $ */ + +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/pcap/scanner.l,v 1.1.1.1 1999/05/02 03:57:55 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include + +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" +#include "gencode.h" +#include "y.tab.h" + +static int stoi(char *); +static inline int xdtoi(int); + +#ifdef FLEX_SCANNER +#undef YY_INPUT +#define YY_INPUT(buf, result, max)\ + {\ + char *src = in_buffer;\ + int i;\ +\ + if (*src == 0)\ + result = YY_NULL;\ + else {\ + for (i = 0; *src && i < max; ++i)\ + buf[i] = *src++;\ + in_buffer += i;\ + result = i;\ + }\ + } +#else +#undef getc +#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) +#endif + +extern YYSTYPE yylval; + +static char *in_buffer; + +%} + +N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) +B ([0-9A-Fa-f][0-9A-Fa-f]?) + +%a 3000 + +%% +dst return DST; +src return SRC; + +link|ether|ppp|slip return LINK; +fddi return LINK; +arp return ARP; +rarp return RARP; +ip return IP; +tcp return TCP; +udp return UDP; +icmp return ICMP; +igmp return IGMP; + +decnet return DECNET; +lat return LAT; +moprc return MOPRC; +mopdl return MOPDL; + +host return HOST; +net return NET; +port return PORT; +proto return PROTO; + +gateway return GATEWAY; + +less return LESS; +greater return GREATER; +byte return BYTE; +broadcast return TK_BROADCAST; +multicast return TK_MULTICAST; + +and|"&&" return AND; +or|"||" return OR; +not return '!'; + +len|length return LEN; +inbound return INBOUND; +outbound return OUTBOUND; + +[ \n\t] ; +[+\-*/:\[\]!<>()&|=] return yytext[0]; +">=" return GEQ; +"<=" return LEQ; +"!=" return NEQ; +"==" return '='; +"<<" return LSH; +">>" return RSH; +{N} { yylval.i = stoi((char *)yytext); return NUM; } +({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { + yylval.s = sdup((char *)yytext); return HID; +} +{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext); + return EID; } +{B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } +[A-Za-z][-_.A-Za-z0-9]* { yylval.s = sdup((char *)yytext); return ID; } +"\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; } +[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { bpf_error("illegal token: %s\n", yytext); } +. { bpf_error("illegal char '%c'", *yytext); } +%% +void +lex_init(buf) + char *buf; +{ + in_buffer = buf; +} + +/* + * Also define a yywrap. Note that if we're using flex, it will + * define a macro to map this identifier to pcap_wrap. + */ +int +yywrap() +{ + return 1; +} + +/* Hex digit to integer. */ +static inline int +xdtoi(c) + register int c; +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +/* + * Convert string to integer. Just like atoi(), but checks for + * preceding 0x or 0 and uses hex or octal instead of decimal. + */ +static int +stoi(s) + char *s; +{ + int base = 10; + int n = 0; + + if (*s == '0') { + if (s[1] == 'x' || s[1] == 'X') { + s += 2; + base = 16; + } + else { + base = 8; + s += 1; + } + } + while (*s) + n = n * base + xdtoi(*s++); + + return n; +} + diff --git a/ping.tproj/Makefile b/ping.tproj/Makefile new file mode 100644 index 0000000..8ad77bf --- /dev/null +++ b/ping.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ping + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ping.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\ + ping.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ping.tproj/Makefile.dist b/ping.tproj/Makefile.dist new file mode 100644 index 0000000..d08f74d --- /dev/null +++ b/ping.tproj/Makefile.dist @@ -0,0 +1,8 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= ping +MAN8= ping.0 +BINOWN= root +BINMODE=4555 + +.include diff --git a/ping.tproj/Makefile.postamble b/ping.tproj/Makefile.postamble new file mode 100644 index 0000000..23e0214 --- /dev/null +++ b/ping.tproj/Makefile.postamble @@ -0,0 +1 @@ +INSTALL_PERMISSIONS = 4555 # If set, 'install' chmod's executable to this diff --git a/ping.tproj/Makefile.preamble b/ping.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/ping.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/ping.tproj/PB.project b/ping.tproj/PB.project new file mode 100644 index 0000000..b7fd3c5 --- /dev/null +++ b/ping.tproj/PB.project @@ -0,0 +1,31 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (ping.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, ping.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = ping; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = ping; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ping; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = ping; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ping.tproj/ping.8 b/ping.tproj/ping.8 new file mode 100644 index 0000000..2382365 --- /dev/null +++ b/ping.tproj/ping.8 @@ -0,0 +1,328 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ping.8 8.3 (Berkeley) 4/28/95 +.\" +.Dd April 28, 1995 +.Dt PING 8 +.Os BSD 4.3 +.Sh NAME +.Nm ping +.Nd send +.Tn ICMP ECHO_REQUEST +packets to network hosts +.Sh SYNOPSIS +.Nm ping +.Op Fl Rdfnqrv +.Op Fl c Ar count +.Op Fl i Ar wait +.Op Fl l Ar preload +.Op Fl p Ar pattern +.Op Fl s Ar packetsize +.Ar host +.Sh DESCRIPTION +.Nm Ping +uses the +.Tn ICMP +protocol's mandatory +.Tn ECHO_REQUEST +datagram to elicit an +.Tn ICMP ECHO_RESPONSE +from a host or gateway. +.Tn ECHO_REQUEST +datagrams (``pings'') have an IP and +.Tn ICMP +header, +followed by a +.Dq struct timeval +and then an arbitrary number of ``pad'' bytes used to fill out the +packet. +The options are as follows: +.Bl -tag -width Ds +.It Fl c Ar count +Stop after sending (and receiving) +.Ar count +.Tn ECHO_RESPONSE +packets. +.It Fl d +Set the +.Dv SO_DEBUG +option on the socket being used. +.It Fl f +Flood ping. +Outputs packets as fast as they come back or one hundred times per second, +whichever is more. +For every +.Tn ECHO_REQUEST +sent a period ``.'' is printed, while for every +.Tn ECHO_REPLY +received a backspace is printed. +This provides a rapid display of how many packets are being dropped. +Only the super-user may use this option. +.Bf -emphasis +This can be very hard on a network and should be used with caution. +.Ef +.It Fl i Ar wait +Wait +.Ar wait +seconds +.Em between sending each packet . +The default is to wait for one second between each packet. +This option is incompatible with the +.Fl f +option. +.It Fl l Ar preload +If +.Ar preload +is specified, +.Nm ping +sends that many packets as fast as possible before falling into its normal +mode of behavior. +.It Fl n +Numeric output only. +No attempt will be made to lookup symbolic names for host addresses. +.It Fl p Ar pattern +You may specify up to 16 ``pad'' bytes to fill out the packet you send. +This is useful for diagnosing data-dependent problems in a network. +For example, +.Dq Li \-p ff +will cause the sent packet to be filled with all +ones. +.It Fl q +Quiet output. +Nothing is displayed except the summary lines at startup time and +when finished. +.It Fl R +Record route. +Includes the +.Tn RECORD_ROUTE +option in the +.Tn ECHO_REQUEST +packet and displays +the route buffer on returned packets. +Note that the IP header is only large enough for nine such routes. +Many hosts ignore or discard this option. +.It Fl r +Bypass the normal routing tables and send directly to a host on an attached +network. +If the host is not on a directly-attached network, an error is returned. +This option can be used to ping a local host through an interface +that has no route through it (e.g., after the interface was dropped by +.Xr routed 8 ) . +.It Fl s Ar packetsize +Specifies the number of data bytes to be sent. +The default is 56, which translates into 64 +.Tn ICMP +data bytes when combined +with the 8 bytes of +.Tn ICMP +header data. +.It Fl v +Verbose output. +.Tn ICMP +packets other than +.Tn ECHO_RESPONSE +that are received are listed. +.El +.Pp +When using +.Nm ping +for fault isolation, it should first be run on the local host, to verify +that the local network interface is up and running. +Then, hosts and gateways further and further away should be ``pinged''. +Round-trip times and packet loss statistics are computed. +If duplicate packets are received, they are not included in the packet +loss calculation, although the round trip time of these packets is used +in calculating the minimum/average/maximum round-trip time numbers. +When the specified number of packets have been sent (and received) or +if the program is terminated with a +.Dv SIGINT , +a brief summary is displayed. +.Pp +This program is intended for use in network testing, measurement and +management. +Because of the load it can impose on the network, it is unwise to use +.Nm ping +during normal operations or from automated scripts. +.Sh ICMP PACKET DETAILS +An IP header without options is 20 bytes. +An +.Tn ICMP +.Tn ECHO_REQUEST +packet contains an additional 8 bytes worth +of +.Tn ICMP +header followed by an arbitrary amount of data. +When a +.Ar packetsize +is given, this indicated the size of this extra piece of data (the +default is 56). +Thus the amount of data received inside of an IP packet of type +.Tn ICMP +.Tn ECHO_REPLY +will always be 8 bytes more than the requested data space +(the +.Tn ICMP +header). +.Pp +If the data space is at least eight bytes large, +.Nm ping +uses the first eight bytes of this space to include a timestamp which +it uses in the computation of round trip times. +If less than eight bytes of pad are specified, no round trip times are +given. +.Sh DUPLICATE AND DAMAGED PACKETS +.Nm Ping +will report duplicate and damaged packets. +Duplicate packets should never occur, and seem to be caused by +inappropriate link-level retransmissions. +Duplicates may occur in many situations and are rarely (if ever) a +good sign, although the presence of low levels of duplicates may not +always be cause for alarm. +.Pp +Damaged packets are obviously serious cause for alarm and often +indicate broken hardware somewhere in the +.Nm ping +packet's path (in the network or in the hosts). +.Sh TRYING DIFFERENT DATA PATTERNS +The (inter)network layer should never treat packets differently depending +on the data contained in the data portion. +Unfortunately, data-dependent problems have been known to sneak into +networks and remain undetected for long periods of time. +In many cases the particular pattern that will have problems is something +that doesn't have sufficient ``transitions'', such as all ones or all +zeros, or a pattern right at the edge, such as almost all zeros. +It isn't necessarily enough to specify a data pattern of all zeros (for +example) on the command line because the pattern that is of interest is +at the data link level, and the relationship between what you type and +what the controllers transmit can be complicated. +.Pp +This means that if you have a data-dependent problem you will probably +have to do a lot of testing to find it. +If you are lucky, you may manage to find a file that either can't be sent +across your network or that takes much longer to transfer than other +similar length files. +You can then examine this file for repeated patterns that you can test +using the +.Fl p +option of +.Nm ping . +.Sh TTL DETAILS +The +.Tn TTL +value of an IP packet represents the maximum number of IP routers +that the packet can go through before being thrown away. +In current practice you can expect each router in the Internet to decrement +the +.Tn TTL +field by exactly one. +.Pp +The +.Tn TCP/IP +specification states that the +.Tn TTL +field for +.Tn TCP +packets should +be set to 60, but many systems use smaller values (4.3 +.Tn BSD +uses 30, 4.2 used +15). +.Pp +The maximum possible value of this field is 255, and most Unix systems set +the +.Tn TTL +field of +.Tn ICMP ECHO_REQUEST +packets to 255. +This is why you will find you can ``ping'' some hosts, but not reach them +with +.Xr telnet 1 +or +.Xr ftp 1 . +.Pp +In normal operation ping prints the ttl value from the packet it receives. +When a remote system receives a ping packet, it can do one of three things +with the +.Tn TTL +field in its response: +.Bl -bullet +.It +Not change it; this is what Berkeley Unix systems did before the +.Bx 4.3 tahoe +release. +In this case the +.Tn TTL +value in the received packet will be 255 minus the +number of routers in the round-trip path. +.It +Set it to 255; this is what current Berkeley Unix systems do. +In this case the +.Tn TTL +value in the received packet will be 255 minus the +number of routers in the path +.Xr from +the remote system +.Em to +the +.Nm ping Ns Em ing +host. +.It +Set it to some other value. +Some machines use the same value for +.Tn ICMP +packets that they use for +.Tn TCP +packets, for example either 30 or 60. +Others may use completely wild values. +.El +.Sh BUGS +Many Hosts and Gateways ignore the +.Tn RECORD_ROUTE +option. +.Pp +The maximum IP header length is too small for options like +.Tn RECORD_ROUTE +to +be completely useful. +There's not much that that can be done about this, however. +.Pp +Flood pinging is not recommended in general, and flood pinging the +broadcast address should only be done under very controlled conditions. +.Sh SEE ALSO +.Xr netstat 1 , +.Xr ifconfig 8 , +.Xr routed 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/ping.tproj/ping.c b/ping.tproj/ping.c new file mode 100644 index 0000000..4aad17e --- /dev/null +++ b/ping.tproj/ping.c @@ -0,0 +1,1018 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Muuss. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * P I N G . C + * + * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, + * measure round-trip-delays and packet loss across network paths. + * + * Author - + * Mike Muuss + * U. S. Army Ballistic Research Laboratory + * December, 1983 + * + * Status - + * Public Domain. Distribution Unlimited. + * Bugs - + * More statistics could always be gathered. + * This program has to run SUID to ROOT to access the ICMP socket. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFDATALEN (64 - 8) /* default data length */ +#define MAXIPLEN 60 +#define MAXICMPLEN 76 +#define MAXPACKET (65536 - 60 - 8)/* max packet size */ +#define MAXWAIT 10 /* max seconds to wait for response */ +#define NROUTES 9 /* number of record route slots */ + +#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */ +#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */ +#define SET(bit) (A(bit) |= B(bit)) +#define CLR(bit) (A(bit) &= (~B(bit))) +#define TST(bit) (A(bit) & B(bit)) + +/* various options */ +int options; +#define F_FLOOD 0x001 +#define F_INTERVAL 0x002 +#define F_NUMERIC 0x004 +#define F_PINGFILLED 0x008 +#define F_QUIET 0x010 +#define F_RROUTE 0x020 +#define F_SO_DEBUG 0x040 +#define F_SO_DONTROUTE 0x080 +#define F_VERBOSE 0x100 + +/* + * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum + * number of received sequence numbers we can keep track of. Change 128 + * to 8192 for complete accuracy... + */ +#define MAX_DUP_CHK (8 * 128) +int mx_dup_ck = MAX_DUP_CHK; +char rcvd_tbl[MAX_DUP_CHK / 8]; + +struct sockaddr whereto; /* who to ping */ +int datalen = DEFDATALEN; +int s; /* socket file descriptor */ +u_char outpack[MAXPACKET]; +char BSPACE = '\b'; /* characters written for flood */ +char DOT = '.'; +char *hostname; +int ident; /* process id to identify our packets */ + +/* counters */ +long npackets; /* max packets to transmit */ +long nreceived; /* # of packets we got back */ +long nrepeats; /* number of duplicates */ +long ntransmitted; /* sequence # for outbound packets = #sent */ +int interval = 1; /* interval between packets */ + +/* timing */ +int timing; /* flag to do timing */ +double tmin = 999999999.0; /* minimum round trip time */ +double tmax = 0.0; /* maximum round trip time */ +double tsum = 0.0; /* sum of all times, for doing average */ + +char *pr_addr(); +void catcher(), finish(); + +main(argc, argv) + int argc; + char **argv; +{ + extern int errno, optind; + extern char *optarg; + struct timeval timeout; + struct hostent *hp; + struct sockaddr_in *to; + struct protoent *proto; + register int i; + int ch, fdmask, hold, packlen, preload; + u_char *datap, *packet; + char *target, hnamebuf[MAXHOSTNAMELEN], *malloc(); +#ifdef IP_OPTIONS + char rspace[3 + 4 * NROUTES + 1]; /* record route space */ +#endif + + preload = 0; + datap = &outpack[8 + sizeof(struct timeval)]; + while ((ch = getopt(argc, argv, "Rc:dfh:i:l:np:qrs:v")) != EOF) + switch(ch) { + case 'c': + npackets = atoi(optarg); + if (npackets <= 0) { + (void)fprintf(stderr, + "ping: bad number of packets to transmit.\n"); + exit(1); + } + break; + case 'd': + options |= F_SO_DEBUG; + break; + case 'f': + if (getuid()) { + (void)fprintf(stderr, + "ping: %s\n", strerror(EPERM)); + exit(1); + } + options |= F_FLOOD; + setbuf(stdout, (char *)NULL); + break; + case 'i': /* wait between sending packets */ + interval = atoi(optarg); + if (interval <= 0) { + (void)fprintf(stderr, + "ping: bad timing interval.\n"); + exit(1); + } + options |= F_INTERVAL; + break; + case 'l': + if (getuid()) { + (void)fprintf(stderr, + "ping: %s\n", strerror(EPERM)); + exit(1); + } + preload = atoi(optarg); + if (preload < 0) { + (void)fprintf(stderr, + "ping: bad preload value.\n"); + exit(1); + } + break; + case 'n': + options |= F_NUMERIC; + break; + case 'p': /* fill buffer with user pattern */ + options |= F_PINGFILLED; + fill((char *)datap, optarg); + break; + case 'q': + options |= F_QUIET; + break; + case 'R': + options |= F_RROUTE; + break; + case 'r': + options |= F_SO_DONTROUTE; + break; + case 's': /* size of packet to send */ + datalen = atoi(optarg); + if (datalen > MAXPACKET) { + (void)fprintf(stderr, + "ping: packet size too large.\n"); + exit(1); + } + if (datalen <= 0) { + (void)fprintf(stderr, + "ping: illegal packet size.\n"); + exit(1); + } + break; + case 'v': + options |= F_VERBOSE; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 1) + usage(); + target = *argv; + + memset(&whereto, 0, sizeof(struct sockaddr)); + to = (struct sockaddr_in *)&whereto; + to->sin_family = AF_INET; + to->sin_addr.s_addr = inet_addr(target); + if (to->sin_addr.s_addr != (u_int)-1) + hostname = target; + else { + hp = gethostbyname(target); + if (!hp) { + (void)fprintf(stderr, + "ping: unknown host %s\n", target); + exit(1); + } + to->sin_family = hp->h_addrtype; + memmove(&to->sin_addr, hp->h_addr, hp->h_length); + (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); + hostname = hnamebuf; + } + + if (options & F_FLOOD && options & F_INTERVAL) { + (void)fprintf(stderr, + "ping: -f and -i incompatible options.\n"); + exit(1); + } + + if (datalen >= sizeof(struct timeval)) /* can we time transfer */ + timing = 1; + packlen = datalen + MAXIPLEN + MAXICMPLEN; + if (!(packet = (u_char *)malloc((u_int)packlen))) { + (void)fprintf(stderr, "ping: out of memory.\n"); + exit(1); + } + if (!(options & F_PINGFILLED)) + for (i = 8; i < datalen; ++i) + *datap++ = i; + + ident = getpid() & 0xFFFF; + + if (!(proto = getprotobyname("icmp"))) { + (void)fprintf(stderr, "ping: unknown protocol icmp.\n"); + exit(1); + } + if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { + perror("ping: socket"); + exit(1); + } + hold = 1; + if (options & F_SO_DEBUG) + (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, + sizeof(hold)); + if (options & F_SO_DONTROUTE) + (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, + sizeof(hold)); + + /* record route option */ + if (options & F_RROUTE) { +#ifdef IP_OPTIONS + rspace[IPOPT_OPTVAL] = IPOPT_RR; + rspace[IPOPT_OLEN] = sizeof(rspace)-1; + rspace[IPOPT_OFFSET] = IPOPT_MINOFF; + if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, + sizeof(rspace)) < 0) { + perror("ping: record route"); + exit(1); + } +#else + (void)fprintf(stderr, + "ping: record route not available in this implementation.\n"); + exit(1); +#endif /* IP_OPTIONS */ + } + + /* + * When pinging the broadcast address, you can get a lot of answers. + * Doing something so evil is useful if you are trying to stress the + * ethernet, or just want to fill the arp cache to get some stuff for + * /etc/ethers. + */ + (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, &packlen, sizeof(packlen)); + + if (to->sin_family == AF_INET) + (void)printf("PING %s (%s): %d data bytes\n", hostname, + inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr), + datalen); + else + (void)printf("PING %s: %d data bytes\n", hostname, datalen); + + (void)signal(SIGINT, finish); + (void)signal(SIGALRM, catcher); + + while (preload--) /* fire off them quickies */ + pinger(); + + if ((options & F_FLOOD) == 0) + catcher(); /* start things going */ + + for (;;) { + struct sockaddr_in from; + register int cc; + int fromlen; + sigset_t omask, nmask; + + if (options & F_FLOOD) { + pinger(); + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + fdmask = 1 << s; + if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout) < 1) + continue; + } + fromlen = sizeof(from); + if ((cc = recvfrom(s, (char *)packet, packlen, 0, + (struct sockaddr *)&from, &fromlen)) < 0) { + if (errno == EINTR) + continue; + perror("ping: recvfrom"); + continue; + } + sigemptyset(&nmask); + sigaddset(&nmask, SIGALRM); + sigprocmask(SIG_BLOCK, &nmask, &omask); + pr_pack((char *)packet, cc, &from); + sigprocmask(SIG_SETMASK, &omask, NULL); + if (npackets && nreceived >= npackets) + break; + } + finish(); + /* NOTREACHED */ +} + +/* + * catcher -- + * This routine causes another PING to be transmitted, and then + * schedules another SIGALRM for 1 second from now. + * + * bug -- + * Our sense of time will slowly skew (i.e., packets will not be + * launched exactly at 1-second intervals). This does not affect the + * quality of the delay and loss statistics. + */ +void +catcher() +{ + int waittime; + + pinger(); + (void)signal(SIGALRM, catcher); + if (!npackets || ntransmitted < npackets) + alarm((u_int)interval); + else { + if (nreceived) { + waittime = 2 * tmax / 1000; + if (!waittime) + waittime = 1; + } else + waittime = MAXWAIT; + (void)signal(SIGALRM, finish); + (void)alarm((u_int)waittime); + } +} + +/* + * pinger -- + * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet + * will be added on by the kernel. The ID field is our UNIX process ID, + * and the sequence number is an ascending integer. The first 8 bytes + * of the data portion are used to hold a UNIX "timeval" struct in VAX + * byte-order, to compute the round-trip time. + */ +pinger() +{ + register struct icmp *icp; + register int cc; + int i; + + icp = (struct icmp *)outpack; + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = ntransmitted++; + icp->icmp_id = ident; /* ID */ + + CLR(icp->icmp_seq % mx_dup_ck); + + if (timing) + (void)gettimeofday((struct timeval *)&outpack[8], + (struct timezone *)NULL); + + cc = datalen + 8; /* skips ICMP portion */ + + /* compute ICMP checksum here */ + icp->icmp_cksum = in_cksum((u_short *)icp, cc); + + i = sendto(s, (char *)outpack, cc, 0, &whereto, + sizeof(struct sockaddr)); + + if (i < 0 || i != cc) { + if (i < 0) + perror("ping: sendto"); + (void)printf("ping: wrote %s %d chars, ret=%d\n", + hostname, cc, i); + } + if (!(options & F_QUIET) && options & F_FLOOD) + (void)write(STDOUT_FILENO, &DOT, 1); +} + +/* + * pr_pack -- + * Print out the packet, if it came from us. This logic is necessary + * because ALL readers of the ICMP socket get a copy of ALL ICMP packets + * which arrive ('tis only fair). This permits multiple copies of this + * program to be run without having intermingled output (or statistics!). + */ +pr_pack(buf, cc, from) + char *buf; + int cc; + struct sockaddr_in *from; +{ + register struct icmp *icp; + register u_long l; + register u_int i, j; + register u_char *cp,*dp; + static int old_rrlen; + static char old_rr[MAX_IPOPTLEN]; + struct ip *ip; + struct timeval tv, *tp; + double triptime; + int hlen, dupflag; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + + /* Check the IP header */ + ip = (struct ip *)buf; + hlen = ip->ip_hl << 2; + if (cc < hlen + ICMP_MINLEN) { + if (options & F_VERBOSE) + (void)fprintf(stderr, + "ping: packet too short (%d bytes) from %s\n", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr)); + return; + } + + /* Now the ICMP part */ + cc -= hlen; + icp = (struct icmp *)(buf + hlen); + if (icp->icmp_type == ICMP_ECHOREPLY) { + if (icp->icmp_id != ident) + return; /* 'Twas not our ECHO */ + ++nreceived; + if (timing) { +#ifndef icmp_data + tp = (struct timeval *)&icp->icmp_ip; +#else + tp = (struct timeval *)icp->icmp_data; +#endif + tvsub(&tv, tp); + triptime = ((double)tv.tv_sec) * 1000.0 + + ((double)tv.tv_usec) / 1000.0; + tsum += triptime; + if (triptime < tmin) + tmin = triptime; + if (triptime > tmax) + tmax = triptime; + } + + if (TST(icp->icmp_seq % mx_dup_ck)) { + ++nrepeats; + --nreceived; + dupflag = 1; + } else { + SET(icp->icmp_seq % mx_dup_ck); + dupflag = 0; + } + + if (options & F_QUIET) + return; + + if (options & F_FLOOD) + (void)write(STDOUT_FILENO, &BSPACE, 1); + else { + (void)printf("%d bytes from %s: icmp_seq=%u", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), + icp->icmp_seq); + (void)printf(" ttl=%d", ip->ip_ttl); + if (timing) + (void)printf(" time=%g ms", triptime); + if (dupflag) + (void)printf(" (DUP!)"); + /* check the data */ + cp = (u_char*)&icp->icmp_data[8]; + dp = &outpack[8 + sizeof(struct timeval)]; + for (i = 8; i < datalen; ++i, ++cp, ++dp) { + if (*cp != *dp) { + (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", + i, *dp, *cp); + cp = (u_char*)&icp->icmp_data[0]; + for (i = 8; i < datalen; ++i, ++cp) { + if ((i % 32) == 8) + (void)printf("\n\t"); + (void)printf("%x ", *cp); + } + break; + } + } + } + } else { + /* We've got something other than an ECHOREPLY */ + if (!(options & F_VERBOSE)) + return; + (void)printf("%d bytes from %s: ", cc, + pr_addr(from->sin_addr.s_addr)); + pr_icmph(icp); + } + + /* Display any IP options */ + cp = (u_char *)buf + sizeof(struct ip); + + for (; hlen > (int)sizeof(struct ip); --hlen, ++cp) + switch (*cp) { + case IPOPT_EOL: + hlen = 0; + break; + case IPOPT_LSRR: + (void)printf("\nLSRR: "); + hlen -= 2; + j = *++cp; + ++cp; + if (j > IPOPT_MINOFF) + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", pr_addr(ntohl(l))); + hlen -= 4; + j -= 4; + if (j <= IPOPT_MINOFF) + break; + (void)putchar('\n'); + } + break; + case IPOPT_RR: + j = *++cp; /* get length */ + i = *++cp; /* and pointer */ + hlen -= 2; + if (i > j) + i = j; + i -= IPOPT_MINOFF; + if (i <= 0) + continue; + if (i == old_rrlen + && cp == (u_char *)buf + sizeof(struct ip) + 2 + && !memcmp(cp, old_rr, i) + && !(options & F_FLOOD)) { + (void)printf("\t(same route)"); + i = ((i + 3) / 4) * 4; + hlen -= i; + cp += i; + break; + } + if (i < MAX_IPOPTLEN) { + old_rrlen = i; + memcpy(old_rr, cp, i); + } else + old_rrlen = 0; + + (void)printf("\nRR: "); + j = 0; + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", pr_addr(ntohl(l))); + hlen -= 4; + i -= 4; + j += 4; + if (i <= 0) + break; + if (j >= MAX_IPOPTLEN) { + (void)printf("\t(truncated route)"); + break; + } + (void)putchar('\n'); + } + break; + case IPOPT_NOP: + (void)printf("\nNOP"); + break; + default: + (void)printf("\nunknown option %x", *cp); + break; + } + if (!(options & F_FLOOD)) { + (void)putchar('\n'); + (void)fflush(stdout); + } +} + +/* + * in_cksum -- + * Checksum routine for Internet Protocol family headers (C Version) + */ +in_cksum(addr, len) + u_short *addr; + int len; +{ + register int nleft = len; + register u_short *w = addr; + register int sum = 0; + u_short answer = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), we add + * sequential 16 bit words to it, and at the end, fold back all the + * carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + *(u_char *)(&answer) = *(u_char *)w ; + sum += answer; + } + + /* add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return(answer); +} + +/* + * tvsub -- + * Subtract 2 timeval structs: out = out - in. Out is assumed to + * be >= in. + */ +tvsub(out, in) + register struct timeval *out, *in; +{ + if ((out->tv_usec -= in->tv_usec) < 0) { + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + +/* + * finish -- + * Print out statistics, and give up. + */ +void +finish() +{ + register int i; + + (void)signal(SIGINT, SIG_IGN); + (void)putchar('\n'); + (void)fflush(stdout); + (void)printf("--- %s ping statistics ---\n", hostname); + (void)printf("%ld packets transmitted, ", ntransmitted); + (void)printf("%ld packets received, ", nreceived); + if (nrepeats) + (void)printf("+%ld duplicates, ", nrepeats); + if (ntransmitted) + if (nreceived > ntransmitted) + (void)printf("-- somebody's printing up packets!"); + else + (void)printf("%d%% packet loss", + (int) (((ntransmitted - nreceived) * 100) / + ntransmitted)); + (void)putchar('\n'); + if (nreceived && timing) { + /* Only display average to microseconds */ + i = 1000.0 * tsum / (nreceived + nrepeats); + (void)printf("round-trip min/avg/max = %g/%g/%g ms\n", + tmin, ((double)i) / 1000.0, tmax); + } + exit(0); +} + +#ifdef notdef +static char *ttab[] = { + "Echo Reply", /* ip + seq + udata */ + "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ + "Source Quench", /* IP */ + "Redirect", /* redirect type, gateway, + IP */ + "Echo", + "Time Exceeded", /* transit, frag reassem + IP */ + "Parameter Problem", /* pointer + IP */ + "Timestamp", /* id + seq + three timestamps */ + "Timestamp Reply", /* " */ + "Info Request", /* id + sq */ + "Info Reply" /* " */ +}; +#endif + +/* + * pr_icmph -- + * Print a descriptive string about an ICMP header. + */ +pr_icmph(icp) + struct icmp *icp; +{ + switch(icp->icmp_type) { + case ICMP_ECHOREPLY: + (void)printf("Echo Reply\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_UNREACH: + switch(icp->icmp_code) { + case ICMP_UNREACH_NET: + (void)printf("Destination Net Unreachable\n"); + break; + case ICMP_UNREACH_HOST: + (void)printf("Destination Host Unreachable\n"); + break; + case ICMP_UNREACH_PROTOCOL: + (void)printf("Destination Protocol Unreachable\n"); + break; + case ICMP_UNREACH_PORT: + (void)printf("Destination Port Unreachable\n"); + break; + case ICMP_UNREACH_NEEDFRAG: + (void)printf("frag needed and DF set\n"); + break; + case ICMP_UNREACH_SRCFAIL: + (void)printf("Source Route Failed\n"); + break; + default: + (void)printf("Dest Unreachable, Bad Code: %d\n", + icp->icmp_code); + break; + } + /* Print returned IP header information */ +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_SOURCEQUENCH: + (void)printf("Source Quench\n"); +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_REDIRECT: + switch(icp->icmp_code) { + case ICMP_REDIRECT_NET: + (void)printf("Redirect Network"); + break; + case ICMP_REDIRECT_HOST: + (void)printf("Redirect Host"); + break; + case ICMP_REDIRECT_TOSNET: + (void)printf("Redirect Type of Service and Network"); + break; + case ICMP_REDIRECT_TOSHOST: + (void)printf("Redirect Type of Service and Host"); + break; + default: + (void)printf("Redirect, Bad Code: %d", icp->icmp_code); + break; + } + (void)printf("(New addr: 0x%08lx)\n", icp->icmp_gwaddr.s_addr); +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_ECHO: + (void)printf("Echo Request\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_TIMXCEED: + switch(icp->icmp_code) { + case ICMP_TIMXCEED_INTRANS: + (void)printf("Time to live exceeded\n"); + break; + case ICMP_TIMXCEED_REASS: + (void)printf("Frag reassembly time exceeded\n"); + break; + default: + (void)printf("Time exceeded, Bad Code: %d\n", + icp->icmp_code); + break; + } +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_PARAMPROB: + (void)printf("Parameter problem: pointer = 0x%02x\n", + icp->icmp_hun.ih_pptr); +#ifndef icmp_data + pr_retip(&icp->icmp_ip); +#else + pr_retip((struct ip *)icp->icmp_data); +#endif + break; + case ICMP_TSTAMP: + (void)printf("Timestamp\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_TSTAMPREPLY: + (void)printf("Timestamp Reply\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_IREQ: + (void)printf("Information Request\n"); + /* XXX ID + Seq */ + break; + case ICMP_IREQREPLY: + (void)printf("Information Reply\n"); + /* XXX ID + Seq */ + break; +#ifdef ICMP_MASKREQ + case ICMP_MASKREQ: + (void)printf("Address Mask Request\n"); + break; +#endif +#ifdef ICMP_MASKREPLY + case ICMP_MASKREPLY: + (void)printf("Address Mask Reply\n"); + break; +#endif + default: + (void)printf("Bad ICMP type: %d\n", icp->icmp_type); + } +} + +/* + * pr_iph -- + * Print an IP header with options. + */ +pr_iph(ip) + struct ip *ip; +{ + int hlen; + u_char *cp; + + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + 20; /* point to options */ + + (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); + (void)printf(" %1x %1x %02x %04x %04x", + ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); + (void)printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, + (ip->ip_off) & 0x1fff); + (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); + (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr)); + (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr)); + /* dump and option bytes */ + while (hlen-- > 20) { + (void)printf("%02x", *cp++); + } + (void)putchar('\n'); +} + +/* + * pr_addr -- + * Return an ascii host address as a dotted quad and optionally with + * a hostname. + */ +char * +pr_addr(l) + u_long l; +{ + struct hostent *hp; + static char buf[80]; + + if ((options & F_NUMERIC) || + !(hp = gethostbyaddr((char *)&l, 4, AF_INET))) + (void)sprintf(buf, "%s", inet_ntoa(*(struct in_addr *)&l)); + else + (void)sprintf(buf, "%s (%s)", hp->h_name, + inet_ntoa(*(struct in_addr *)&l)); + return(buf); +} + +/* + * pr_retip -- + * Dump some info on a returned (via ICMP) IP packet. + */ +pr_retip(ip) + struct ip *ip; +{ + int hlen; + u_char *cp; + + pr_iph(ip); + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + hlen; + + if (ip->ip_p == 6) + (void)printf("TCP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + else if (ip->ip_p == 17) + (void)printf("UDP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); +} + +fill(bp, patp) + char *bp, *patp; +{ + register int ii, jj, kk; + int pat[16]; + char *cp; + + for (cp = patp; *cp; cp++) + if (!isxdigit(*cp)) { + (void)fprintf(stderr, + "ping: patterns must be specified as hex digits.\n"); + exit(1); + } + ii = sscanf(patp, + "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", + &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], + &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], + &pat[13], &pat[14], &pat[15]); + + if (ii > 0) + for (kk = 0; + kk <= MAXPACKET - (8 + sizeof(struct timeval) + ii); + kk += ii) + for (jj = 0; jj < ii; ++jj) + bp[jj + kk] = pat[jj]; + if (!(options & F_QUIET)) { + (void)printf("PATTERN: 0x"); + for (jj = 0; jj < ii; ++jj) + (void)printf("%02x", bp[jj] & 0xFF); + (void)printf("\n"); + } +} + +usage() +{ + (void)fprintf(stderr, + "usage: ping [-Rdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] host\n"); + exit(1); +} diff --git a/portmap.tproj/Makefile b/portmap.tproj/Makefile new file mode 100644 index 0000000..5a91e65 --- /dev/null +++ b/portmap.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = portmap + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = portmap.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble portmap.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/portmap.tproj/Makefile.postamble b/portmap.tproj/Makefile.postamble new file mode 100644 index 0000000..f5c79e2 --- /dev/null +++ b/portmap.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/portmap.tproj/Makefile.preamble b/portmap.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/portmap.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/portmap.tproj/PB.project b/portmap.tproj/PB.project new file mode 100644 index 0000000..b9275bb --- /dev/null +++ b/portmap.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (portmap.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, portmap.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = portmap; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/portmap.tproj/portmap.8 b/portmap.tproj/portmap.8 new file mode 100644 index 0000000..a651f5f --- /dev/null +++ b/portmap.tproj/portmap.8 @@ -0,0 +1,110 @@ +.\" Copyright (c) 1987 Sun Microsystems +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)portmap.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt PORTMAP 8 +.Os BSD 4.3 +.Sh NAME +.Nm portmap +.Nd +.Tn DARPA +port to +.Tn RPC +program number mapper +.Sh SYNOPSIS +.Nm portmap +.Op Fl d +.Sh DESCRIPTION +.Nm Portmap +is a server that converts +.Tn RPC +program numbers into +.Tn DARPA +protocol port numbers. +It must be running in order to make +.Tn RPC +calls. +.Pp +When an +.Tn RPC +server is started, it will tell +.Nm portmap +what port number it is listening to, and what +.Tn RPC +program numbers it is prepared to serve. +When a client wishes to make an +.Tn RPC +call to a given program number, +it will first contact +.Nm portmap +on the server machine to determine +the port number where +.Tn RPC +packets should be sent. +.Pp +.Nm Portmap +must be started before any +.Tn RPC +servers are invoked. +.Pp +Normally +.Nm portmap +forks and dissociates itself from the terminal +like any other daemon. +.Nm Portmap +then logs errors using +.Xr syslog 3 . +.Pp +Option available: +.Bl -tag -width Ds +.It Fl d +(debug) prevents +.Nm portmap +from running as a daemon, +and causes errors and debugging information +to be printed to the standard error output. +.El +.Sh SEE ALSO +.Xr inetd.conf 5 , +.Xr rpcinfo 8 , +.Xr inetd 8 +.Sh BUGS +If +.Nm portmap +crashes, all servers must be restarted. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 diff --git a/portmap.tproj/portmap.c b/portmap.tproj/portmap.c new file mode 100644 index 0000000..8a6c53c --- /dev/null +++ b/portmap.tproj/portmap.c @@ -0,0 +1,661 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)portmap.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* +@(#)portmap.c 2.3 88/08/11 4.0 RPCSRC +static char sccsid[] = "@(#)portmap.c 1.32 87/08/06 Copyr 1984 Sun Micro"; +*/ + +/* + * portmap.c, Implements the program,version to port number mapping for + * rpc. + */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NETINFO_TAG_NETWORK "network" +#define NETINFO_NETWORK_DIR_PATH "/var/db/netinfo/network.nidb" +#define NETINFO_STAT_LATENCY 30 + +static int have_tag_network = 0; +static struct timeval last_network_stat = {0, 0}; + +void reg_service(); +void reap(); +static void callit(); +struct pmaplist *pmaplist; +int debugging = 0; +extern int errno; +extern int svc_maxfd; + +extern int get_myaddress(); + +static void +portmap_svc_run() +{ + fd_set readfds; + int status; + + for (;;) + { + readfds = svc_fdset; + switch ((status = select(svc_maxfd+1, &readfds, NULL, NULL, NULL))) + { + case -1: + if (errno == EINTR) continue; + + if ((errno == EFAULT) || (errno == EINVAL)) + { + syslog(LOG_ERR, "aborting - select error %d (%s)", + errno, strerror(errno)); + return; + } + + syslog(LOG_NOTICE, "ignoring select error %d (%s)", + errno, strerror(errno)); + continue; + + case 0: + continue; + + default: + svc_getreqset(&readfds); + } + } +} + +int +main(argc, argv) + int argc; + char **argv; +{ + SVCXPRT *xprt; + int sock, c; + struct sockaddr_in addr; + int len = sizeof(struct sockaddr_in); + register struct pmaplist *pml; + + while ((c = getopt(argc, argv, "d")) != EOF) { + switch (c) { + + case 'd': + debugging = 1; + break; + + default: + (void) fprintf(stderr, "usage: %s [-d]\n", argv[0]); + exit(1); + } + } + + if (!debugging && daemon(0, 0)) { + (void) fprintf(stderr, "portmap: fork: %s", strerror(errno)); + exit(1); + } + + openlog("portmap", debugging ? LOG_PID | LOG_PERROR : LOG_PID, + LOG_DAEMON); + + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + syslog(LOG_ERR, "cannot create udp socket: %m"); + exit(1); + } + + addr.sin_addr.s_addr = 0; + addr.sin_family = AF_INET; + addr.sin_port = htons(PMAPPORT); + if (bind(sock, (struct sockaddr *)&addr, len) != 0) { + syslog(LOG_ERR, "cannot bind udp: %m"); + exit(1); + } + + if ((xprt = svcudp_create(sock)) == (SVCXPRT *)NULL) { + syslog(LOG_ERR, "couldn't do udp_create"); + exit(1); + } + /* make an entry for ourself */ + pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); + pml->pml_next = 0; + pml->pml_map.pm_prog = PMAPPROG; + pml->pml_map.pm_vers = PMAPVERS; + pml->pml_map.pm_prot = IPPROTO_UDP; + pml->pml_map.pm_port = PMAPPORT; + pmaplist = pml; + + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + syslog(LOG_ERR, "cannot create tcp socket: %m"); + exit(1); + } + if (bind(sock, (struct sockaddr *)&addr, len) != 0) { + syslog(LOG_ERR, "cannot bind udp: %m"); + exit(1); + } + if ((xprt = svctcp_create(sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE)) + == (SVCXPRT *)NULL) { + syslog(LOG_ERR, "couldn't do tcp_create"); + exit(1); + } + /* make an entry for ourself */ + pml = (struct pmaplist *)malloc((u_int)sizeof(struct pmaplist)); + pml->pml_map.pm_prog = PMAPPROG; + pml->pml_map.pm_vers = PMAPVERS; + pml->pml_map.pm_prot = IPPROTO_TCP; + pml->pml_map.pm_port = PMAPPORT; + pml->pml_next = pmaplist; + pmaplist = pml; + + (void)svc_register(xprt, PMAPPROG, PMAPVERS, reg_service, FALSE); + + /* initialize "network.nidb" timer */ + gettimeofday(&last_network_stat, NULL); + + (void)signal(SIGCHLD, reap); + portmap_svc_run(); + syslog(LOG_ERR, "run_svc returned unexpectedly"); + abort(); +} + +#ifndef lint +/* need to override perror calls in rpc library */ +__private_extern__ +void +perror(what) + const char *what; +{ + + syslog(LOG_ERR, "%s: %m", what); +} +#endif + +static struct pmaplist * +find_service(prog, vers, prot) + u_long prog, vers, prot; +{ + register struct pmaplist *hit = NULL; + register struct pmaplist *pml; + + for (pml = pmaplist; pml != NULL; pml = pml->pml_next) { + if ((pml->pml_map.pm_prog != prog) || + (pml->pml_map.pm_prot != prot)) + continue; + hit = pml; + if (pml->pml_map.pm_vers == vers) + break; + } + return (hit); +} + +/* + * 1 OK, 0 not + */ +void +reg_service(rqstp, xprt) + struct svc_req *rqstp; + SVCXPRT *xprt; +{ + struct pmap reg; + struct pmaplist *pml, *prevpml, *fnd; + int ans, port; + caddr_t t; + + if (debugging) + (void) fprintf(stderr, "server: about do a switch\n"); + switch (rqstp->rq_proc) { + + case PMAPPROC_NULL: + /* + * Null proc call + */ + if (!svc_sendreply(xprt, xdr_void, (caddr_t)0) && debugging) { + abort(); + } + break; + + case PMAPPROC_SET: + /* + * Set a program,version to port mapping + */ + if (!svc_getargs(xprt, xdr_pmap, ®)) + svcerr_decode(xprt); + else { + /* + * check to see if already used + * find_service returns a hit even if + * the versions don't match, so check for it + */ + fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); + if (fnd && fnd->pml_map.pm_vers == reg.pm_vers) { + if (fnd->pml_map.pm_port == reg.pm_port) { + ans = 1; + goto done; + } + else { + ans = 0; + goto done; + } + } else { + /* + * add to END of list + */ + pml = (struct pmaplist *) + malloc((u_int)sizeof(struct pmaplist)); + pml->pml_map = reg; + pml->pml_next = 0; + if (pmaplist == 0) { + pmaplist = pml; + } else { + for (fnd= pmaplist; fnd->pml_next != 0; + fnd = fnd->pml_next); + fnd->pml_next = pml; + } + ans = 1; + } + done: + if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && + debugging) { + (void) fprintf(stderr, "svc_sendreply\n"); + abort(); + } + } + break; + + case PMAPPROC_UNSET: + /* + * Remove a program,version to port mapping. + */ + if (!svc_getargs(xprt, xdr_pmap, ®)) + svcerr_decode(xprt); + else { + ans = 0; + for (prevpml = NULL, pml = pmaplist; pml != NULL; ) { + if ((pml->pml_map.pm_prog != reg.pm_prog) || + (pml->pml_map.pm_vers != reg.pm_vers)) { + /* both pml & prevpml move forwards */ + prevpml = pml; + pml = pml->pml_next; + continue; + } + /* found it; pml moves forward, prevpml stays */ + ans = 1; + t = (caddr_t)pml; + pml = pml->pml_next; + if (prevpml == NULL) + pmaplist = pml; + else + prevpml->pml_next = pml; + free(t); + } + if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&ans)) && + debugging) { + (void) fprintf(stderr, "svc_sendreply\n"); + abort(); + } + } + break; + + case PMAPPROC_GETPORT: + /* + * Lookup the mapping for a program,version and return its port + */ + if (!svc_getargs(xprt, xdr_pmap, ®)) + svcerr_decode(xprt); + else { + fnd = find_service(reg.pm_prog, reg.pm_vers, reg.pm_prot); + if (fnd) + port = fnd->pml_map.pm_port; + else + port = 0; + if ((!svc_sendreply(xprt, xdr_long, (caddr_t)&port)) && + debugging) { + (void) fprintf(stderr, "svc_sendreply\n"); + abort(); + } + } + break; + + case PMAPPROC_DUMP: + /* + * Return the current set of mapped program,version + */ + if (!svc_getargs(xprt, xdr_void, NULL)) + svcerr_decode(xprt); + else { + if ((!svc_sendreply(xprt, xdr_pmaplist, + (caddr_t)&pmaplist)) && debugging) { + (void) fprintf(stderr, "svc_sendreply\n"); + abort(); + } + } + break; + + case PMAPPROC_CALLIT: + /* + * Calls a procedure on the local machine. If the requested + * procedure is not registered this procedure does not return + * error information!! + * This procedure is only supported on rpc/udp and calls via + * rpc/udp. It passes null authentication parameters. + */ + callit(rqstp, xprt); + break; + + default: + svcerr_noproc(xprt); + break; + } +} + + +/* + * Stuff for the rmtcall service + */ +#define ARGSIZE 9000 + +struct encap_parms { + u_long arglen; + char *args; +}; + +static bool_t +xdr_encap_parms(xdrs, epp) + XDR *xdrs; + struct encap_parms *epp; +{ + return (xdr_bytes(xdrs, &(epp->args), (int *)&(epp->arglen), ARGSIZE)); +} + +struct rmtcallargs { + u_long rmt_prog; + u_long rmt_vers; + u_long rmt_port; + u_long rmt_proc; + struct encap_parms rmt_args; +}; + +static bool_t +xdr_rmtcall_args(xdrs, cap) + register XDR *xdrs; + register struct rmtcallargs *cap; +{ + + /* does not get a port number */ + if (xdr_u_long(xdrs, &(cap->rmt_prog)) && + xdr_u_long(xdrs, &(cap->rmt_vers)) && + xdr_u_long(xdrs, &(cap->rmt_proc))) { + return (xdr_encap_parms(xdrs, &(cap->rmt_args))); + } + return (FALSE); +} + +static bool_t +xdr_rmtcall_result(xdrs, cap) + register XDR *xdrs; + register struct rmtcallargs *cap; +{ + if (xdr_u_long(xdrs, &(cap->rmt_port))) + return (xdr_encap_parms(xdrs, &(cap->rmt_args))); + return (FALSE); +} + +/* + * only worries about the struct encap_parms part of struct rmtcallargs. + * The arglen must already be set!! + */ +static bool_t +xdr_opaque_parms(xdrs, cap) + XDR *xdrs; + struct rmtcallargs *cap; +{ + + return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen)); +} + +/* + * This routine finds and sets the length of incoming opaque paraters + * and then calls xdr_opaque_parms. + */ +static bool_t +xdr_len_opaque_parms(xdrs, cap) + register XDR *xdrs; + struct rmtcallargs *cap; +{ + register u_int beginpos, lowpos, highpos, currpos, pos; + + beginpos = lowpos = pos = xdr_getpos(xdrs); + highpos = lowpos + ARGSIZE; + while ((int)(highpos - lowpos) >= 0) { + currpos = (lowpos + highpos) / 2; + if (xdr_setpos(xdrs, currpos)) { + pos = currpos; + lowpos = currpos + 1; + } else { + highpos = currpos - 1; + } + } + xdr_setpos(xdrs, beginpos); + cap->rmt_args.arglen = pos - beginpos; + return (xdr_opaque_parms(xdrs, cap)); +} + +/* + * Call a remote procedure service + * This procedure is very quiet when things go wrong. + * The proc is written to support broadcast rpc. In the broadcast case, + * a machine should shut-up instead of complain, less the requestor be + * overrun with complaints at the expense of not hearing a valid reply ... + * + * This now forks so that the program & process that it calls can call + * back to the portmapper. + */ +static void +callit(rqstp, xprt) + struct svc_req *rqstp; + SVCXPRT *xprt; +{ + struct rmtcallargs a; + struct pmaplist *pml; + u_short port; + struct sockaddr_in me; + int pid, so = -1; + CLIENT *client; + struct authunix_parms *au = (struct authunix_parms *)rqstp->rq_clntcred; + struct timeval timeout; + char buf[ARGSIZE]; + char tag[MAXPATHLEN]; + int off, taglen; + unsigned int delta; + struct stat sb; + struct timeval now; + + timeout.tv_sec = 5; + timeout.tv_usec = 0; + a.rmt_args.args = buf; + if (!svc_getargs(xprt, xdr_rmtcall_args, &a)) + return; + + /* + * Drop NIBIND_BIND calls for the parent tag "network" if the database + * doesn't exist. This prevents excessive fork() calls. + */ + if ((have_tag_network == 0) && (a.rmt_prog == NIBIND_PROG) && (a.rmt_proc == NIBIND_BIND)) + { + /* Skip sender address and child tag */ + memmove(&taglen, a.rmt_args.args + 4, 4); + taglen = ntohl(taglen); + off = 8 + (((taglen + 3) / 4) * 4); + + /* Get parent tag */ + memmove(&taglen, a.rmt_args.args + off, 4); + taglen = ntohl(taglen); + if (taglen >= MAXPATHLEN) return; + + off += 4; + memmove(tag, a.rmt_args.args + off, taglen); + tag[taglen] = '\0'; + + /* + * If there was no network.nidb a few seconds ago, drop the requset. + */ + if (!strcmp(tag, NETINFO_TAG_NETWORK)) + { + gettimeofday(&now, NULL); + delta = now.tv_sec - last_network_stat.tv_sec; + if (delta < NETINFO_STAT_LATENCY) return; + + if (stat(NETINFO_NETWORK_DIR_PATH, &sb) < 0) + { + last_network_stat = now; + return; + } + + have_tag_network = 1; + } + } + + if ((pml = find_service(a.rmt_prog, a.rmt_vers, + (u_long)IPPROTO_UDP)) == NULL) + return; + /* + * fork a child to do the work. Parent immediately returns. + * Child exits upon completion. + */ + if ((pid = fork()) != 0) { + if (pid < 0) + syslog(LOG_ERR, "CALLIT (prog %lu): fork: %m", + a.rmt_prog); + return; + } + port = pml->pml_map.pm_port; + get_myaddress(&me); + me.sin_port = htons(port); + client = clntudp_create(&me, a.rmt_prog, a.rmt_vers, timeout, &so); + if (client != (CLIENT *)NULL) { + if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) { + client->cl_auth = authunix_create(au->aup_machname, + au->aup_uid, au->aup_gid, au->aup_len, au->aup_gids); + } + a.rmt_port = (u_long)port; + if (clnt_call(client, a.rmt_proc, xdr_opaque_parms, &a, + xdr_len_opaque_parms, &a, timeout) == RPC_SUCCESS) { + svc_sendreply(xprt, xdr_rmtcall_result, (caddr_t)&a); + } + AUTH_DESTROY(client->cl_auth); + clnt_destroy(client); + } + (void)close(so); + exit(0); +} + +void +reap() +{ + while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0); +} diff --git a/rarpd.tproj/Makefile b/rarpd.tproj/Makefile new file mode 100644 index 0000000..34700cd --- /dev/null +++ b/rarpd.tproj/Makefile @@ -0,0 +1,52 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rarpd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = rarpd.c + +OTHERSRCS = Makefile.dist Makefile.preamble rarpd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +HEADER_PATHS = -I. +NEXTSTEP_PB_CFLAGS = -DTFTP_DIR=\"/tftpboot\" +WINDOWS_PB_CFLAGS = -DTFTP_DIR=\"/tftpboot\" +PDO_UNIX_PB_CFLAGS = -DTFTP_DIR=\"/tftpboot\" + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rarpd.tproj/Makefile.dist b/rarpd.tproj/Makefile.dist new file mode 100644 index 0000000..2c02ca5 --- /dev/null +++ b/rarpd.tproj/Makefile.dist @@ -0,0 +1,10 @@ +# @(#) $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $ + +PROG= rarpd +SRCS= rarpd.c + +CFLAGS+=-I${.CURDIR} -DTFTP_DIR=\"/tftpboot\" + +MAN8= rarpd.0 + +.include diff --git a/rarpd.tproj/Makefile.preamble b/rarpd.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/rarpd.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/rarpd.tproj/PB.project b/rarpd.tproj/PB.project new file mode 100644 index 0000000..8c54327 --- /dev/null +++ b/rarpd.tproj/PB.project @@ -0,0 +1,37 @@ +{ + FILESTABLE = { + C_FILES = (); + HEADERSEARCH = (.); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (rarpd.c); + OTHER_SOURCES = (Makefile.dist, Makefile.preamble, rarpd.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = "-DTFTP_DIR=\\\"/tftpboot\\\""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = "-DTFTP_DIR=\\\"/tftpboot\\\""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rarpd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = "-DTFTP_DIR=\\\"/tftpboot\\\""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rarpd.tproj/rarpd.8 b/rarpd.tproj/rarpd.8 new file mode 100644 index 0000000..f090c47 --- /dev/null +++ b/rarpd.tproj/rarpd.8 @@ -0,0 +1,92 @@ +.\" +.\" Copyright (c) 1988-1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that: (1) source code distributions +.\" retain the above copyright notice and this paragraph in its entirety, (2) +.\" distributions including binary code include the above copyright notice and +.\" this paragraph in its entirety in the documentation or other materials +.\" provided with the distribution, and (3) all advertising materials mentioning +.\" features or use of this software display the following acknowledgement: +.\" ``This product includes software developed by the University of California, +.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of +.\" the University nor the names of its contributors may be used to endorse +.\" or promote products derived from this software without specific prior +.\" written permission. +.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED +.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +.\" @(#) $Id: rarpd.8,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $ +.\" +.Dd October 26, 1990 +.Dt RARPD 8 +.Sh NAME +.Nm rarpd +.Nd Reverse ARP Daemon +.Sh SYNOPSIS +.Nm rarpd +.Op Fl adf +.Op Ar interface +.Sh DESCRIPTION +.Nm Rarpd +services Reverse ARP requests on the Ethernet connected to +.Ar interface. +Upon receiving a request, +.Nm rarpd +maps the target hardware address to an IP address via its name, which +must be present in both the +.Xr ethers 5 +and +.Xr hosts 5 +databases. +If a host does not exist in both databases, the translation cannot +proceed and a reply will not be sent. +.Pp +Additionally, a request is honored only if the server +(i.e., the host that rarpd is running on) +can "boot" the target; that is, if the directory +.Pa /tftpboot/ Ns Em ipaddr +exists, where +.Rm ipaddr +is the target IP address. +.Pp +In normal operation, +.Nm rarpd +forks a copy of itself and runs in +the background. Anomalies and errors are reported via +.Xr syslog 3 . +.Sh OPTIONS +.Bl -tag -width indent +.It Fl a +Listen on all the Ethernets attached to the system. +If +.Sq Fl a +is omitted, an interface must be specified. +.It Fl d +Run in debug mode, with all the output to stderr. +This option implies the +.Fl f +option. +.It Fl f +Run in the foreground. +.El +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /etc/ethers +.It Pa /etc/hosts +.It Pa /tftpboot +.El +.Sh SEE ALSO +.Xr bpf 4 , +.Rs +.%R A Reverse Address Resolution Protocol +.%N RFC 903 +.%A Finlayson, R. +.%A Mann, T. +.%A Mogul, J.C. +.%A Theimer, M. +.Re +.Sh AUTHORS +Craig Leres (leres@ee.lbl.gov) and Steven McCanne (mccanne@ee.lbl.gov). +Lawrence Berkeley Laboratory, University of California, Berkeley, CA. diff --git a/rarpd.tproj/rarpd.c b/rarpd.tproj/rarpd.c new file mode 100644 index 0000000..890be78 --- /dev/null +++ b/rarpd.tproj/rarpd.c @@ -0,0 +1,831 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1990 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char rcsid[] = +"@(#) $Id: rarpd.c,v 1.1.1.1 1999/05/02 03:57:59 wsanchez Exp $"; +#endif + + +/* + * rarpd - Reverse ARP Daemon + * + * Usage: rarpd -a [ -d -f ] + * rarpd [ -d -f ] interface + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define FATAL 1 /* fatal error occurred */ +#define NONFATAL 0 /* non fatal error occurred */ + +/* + * The structure for each interface. + */ +struct if_info { + int ii_fd; /* BPF file descriptor */ + u_char ii_eaddr[6]; /* Ethernet address of this interface */ + u_long ii_ipaddr; /* IP address of this interface */ + u_long ii_netmask; /* subnet or net mask */ + struct if_info *ii_next; +}; +/* + * The list of all interfaces that are being listened to. rarp_loop() + * "selects" on the descriptors in this list. + */ +struct if_info *iflist; + +int rarp_open __P((char *)); +int rarp_bootable __P((u_long)); +void init_one __P((char *)); +void init_all __P((void)); +void rarp_loop __P((void)); +void lookup_eaddr __P((char *, u_char *)); +void lookup_ipaddr __P((char *, u_long *, u_long *)); +void usage __P((void)); +void rarp_process __P((struct if_info *, u_char *)); +void rarp_reply __P((struct if_info *, struct ether_header *, u_long)); +void update_arptab __P((u_char *, u_long)); +void err __P((int, const char *,...)); +void debug __P((const char *,...)); +u_long ipaddrtonetmask __P((u_long)); + +int aflag = 0; /* listen on "all" interfaces */ +int dflag = 0; /* print debugging messages */ +int fflag = 0; /* don't fork */ + +void +main(argc, argv) + int argc; + char **argv; +{ + int op, pid, devnull, f; + char *ifname, *hostname, *name; + + extern char *optarg; + extern int optind, opterr; + + if (name = strrchr(argv[0], '/')) + ++name; + else + name = argv[0]; + if (*name == '-') + ++name; + + /* All error reporting is done through syslogs. */ + openlog(name, LOG_PID | LOG_CONS, LOG_DAEMON); + + opterr = 0; + while ((op = getopt(argc, argv, "adf")) != EOF) { + switch (op) { + case 'a': + ++aflag; + break; + + case 'd': + ++dflag; + break; + + case 'f': + ++fflag; + break; + + default: + usage(); + /* NOTREACHED */ + } + } + ifname = argv[optind++]; + hostname = ifname ? argv[optind] : 0; + if ((aflag && ifname) || (!aflag && ifname == 0)) + usage(); + + if (aflag) + init_all(); + else + init_one(ifname); + + if ((!fflag) && (!dflag)) { + pid = fork(); + if (pid > 0) + /* Parent exits, leaving child in background. */ + exit(0); + else + if (pid == -1) { + err(FATAL, "cannot fork"); + /* NOTREACHED */ + } + /* Fade into the background */ + f = open("/dev/tty", O_RDWR); + if (f >= 0) { + if (ioctl(f, TIOCNOTTY, 0) < 0) { + err(FATAL, "TIOCNOTTY: %s", strerror(errno)); + /* NOTREACHED */ + } + (void) close(f); + } + (void) chdir("/"); + (void) setpgrp(0, getpid()); + devnull = open("/dev/null", O_RDWR); + if (devnull >= 0) { + (void) dup2(devnull, 0); + (void) dup2(devnull, 1); + (void) dup2(devnull, 2); + if (devnull > 2) + (void) close(devnull); + } + } + rarp_loop(); +} +/* + * Add 'ifname' to the interface list. Lookup its IP address and network + * mask and Ethernet address, and open a BPF file for it. + */ +void +init_one(ifname) + char *ifname; +{ + struct if_info *p; + + p = (struct if_info *)malloc(sizeof(*p)); + if (p == 0) { + err(FATAL, "malloc: %s", strerror(errno)); + /* NOTREACHED */ + } + p->ii_next = iflist; + iflist = p; + + p->ii_fd = rarp_open(ifname); + lookup_eaddr(ifname, p->ii_eaddr); + lookup_ipaddr(ifname, &p->ii_ipaddr, &p->ii_netmask); +} +/* + * Initialize all "candidate" interfaces that are in the system + * configuration list. A "candidate" is up, not loopback and not + * point to point. + */ +void +init_all() +{ + char inbuf[8192]; + struct ifconf ifc; + struct ifreq *ifr; + int fd; + int i, len; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + err(FATAL, "socket: %s", strerror(errno)); + /* NOTREACHED */ + } + + ifc.ifc_len = sizeof(inbuf); + ifc.ifc_buf = inbuf; + if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + err(FATAL, "init_all: SIOCGIFCONF: %s", strerror(errno)); + /* NOTREACHED */ + } + ifr = ifc.ifc_req; + for (i = 0; i < ifc.ifc_len; + i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) { + len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; + if (ioctl(fd, SIOCGIFFLAGS, (caddr_t)ifr) < 0) { + err(FATAL, "init_all: SIOCGIFFLAGS: %s", + strerror(errno)); + /* NOTREACHED */ + } + if ((ifr->ifr_flags & + (IFF_UP | IFF_LOOPBACK | IFF_POINTOPOINT)) != IFF_UP) + continue; + init_one(ifr->ifr_name); + } + (void) close(fd); +} + +void +usage() +{ + (void) fprintf(stderr, "usage: rarpd -a [ -d -f ]\n"); + (void) fprintf(stderr, " rarpd [ -d -f ] interface\n"); + exit(1); +} + +static int +bpf_open() +{ + int fd; + int n = 0; + char device[sizeof "/dev/bpf000"]; + + /* Go through all the minors and find one that isn't in use. */ + do { + (void) sprintf(device, "/dev/bpf%d", n++); + fd = open(device, O_RDWR); + } while (fd < 0 && errno == EBUSY); + + if (fd < 0) { + err(FATAL, "%s: %s", device, strerror(errno)); + /* NOTREACHED */ + } + return fd; +} +/* + * Open a BPF file and attach it to the interface named 'device'. + * Set immediate mode, and set a filter that accepts only RARP requests. + */ +int +rarp_open(device) + char *device; +{ + int fd; + struct ifreq ifr; + u_int dlt; + int immediate; + + static struct bpf_insn insns[] = { + BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12), + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ETHERTYPE_REVARP, 0, 3), + BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20), + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, ARPOP_REVREQUEST, 0, 1), + BPF_STMT(BPF_RET | BPF_K, sizeof(struct ether_arp) + + sizeof(struct ether_header)), + BPF_STMT(BPF_RET | BPF_K, 0), + }; + static struct bpf_program filter = { + sizeof insns / sizeof(insns[0]), + insns + }; + + fd = bpf_open(); + + /* Set immediate mode so packets are processed as they arrive. */ + immediate = 1; + if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) { + err(FATAL, "BIOCIMMEDIATE: %s", strerror(errno)); + /* NOTREACHED */ + } + (void) strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name); + if (ioctl(fd, BIOCSETIF, (caddr_t) & ifr) < 0) { + err(FATAL, "BIOCSETIF: %s", strerror(errno)); + /* NOTREACHED */ + } + /* Check that the data link layer is an Ethernet; this code won't work + * with anything else. */ + if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) { + err(FATAL, "BIOCGDLT: %s", strerror(errno)); + /* NOTREACHED */ + } + if (dlt != DLT_EN10MB) { + err(FATAL, "%s is not an ethernet", device); + /* NOTREACHED */ + } + /* Set filter program. */ + if (ioctl(fd, BIOCSETF, (caddr_t) & filter) < 0) { + err(FATAL, "BIOCSETF: %s", strerror(errno)); + /* NOTREACHED */ + } + return fd; +} +/* + * Perform various sanity checks on the RARP request packet. Return + * false on failure and log the reason. + */ +static int +rarp_check(p, len) + u_char *p; + int len; +{ + struct ether_header *ep = (struct ether_header *) p; + struct ether_arp *ap = (struct ether_arp *) (p + sizeof(*ep)); + + (void) debug("got a packet"); + + if (len < sizeof(*ep) + sizeof(*ap)) { + err(NONFATAL, "truncated request"); + return 0; + } + /* XXX This test might be better off broken out... */ + if (ntohs (ep->ether_type) != ETHERTYPE_REVARP || + ntohs (ap->arp_hrd) != ARPHRD_ETHER || + ntohs (ap->arp_op) != ARPOP_REVREQUEST || + ntohs (ap->arp_pro) != ETHERTYPE_IP || + ap->arp_hln != 6 || ap->arp_pln != 4) { + err(NONFATAL, "request fails sanity check"); + return 0; + } + if (bcmp((char *) &ep->ether_shost, (char *) &ap->arp_sha, 6) != 0) { + err(NONFATAL, "ether/arp sender address mismatch"); + return 0; + } + if (bcmp((char *) &ap->arp_sha, (char *) &ap->arp_tha, 6) != 0) { + err(NONFATAL, "ether/arp target address mismatch"); + return 0; + } + return 1; +} + +/* + * Loop indefinitely listening for RARP requests on the + * interfaces in 'iflist'. + */ +void +rarp_loop() +{ + u_char *buf, *bp, *ep; + int cc, fd; + fd_set fds, listeners; + int bufsize, maxfd = 0; + struct if_info *ii; + + if (iflist == 0) { + err(FATAL, "no interfaces"); + /* NOTREACHED */ + } + if (ioctl(iflist->ii_fd, BIOCGBLEN, (caddr_t) & bufsize) < 0) { + err(FATAL, "BIOCGBLEN: %s", strerror(errno)); + /* NOTREACHED */ + } + buf = (u_char *) malloc((unsigned) bufsize); + if (buf == 0) { + err(FATAL, "malloc: %s", strerror(errno)); + /* NOTREACHED */ + } + /* + * Find the highest numbered file descriptor for select(). + * Initialize the set of descriptors to listen to. + */ + FD_ZERO(&fds); + for (ii = iflist; ii; ii = ii->ii_next) { + FD_SET(ii->ii_fd, &fds); + if (ii->ii_fd > maxfd) + maxfd = ii->ii_fd; + } + while (1) { + listeners = fds; + if (select(maxfd + 1, &listeners, (struct fd_set *) 0, + (struct fd_set *) 0, (struct timeval *) 0) < 0) { + err(FATAL, "select: %s", strerror(errno)); + /* NOTREACHED */ + } + for (ii = iflist; ii; ii = ii->ii_next) { + fd = ii->ii_fd; + if (!FD_ISSET(fd, &listeners)) + continue; + again: + cc = read(fd, (char *) buf, bufsize); + /* Don't choke when we get ptraced */ + if (cc < 0 && errno == EINTR) + goto again; + /* Due to a SunOS bug, after 2^31 bytes, the file + * offset overflows and read fails with EINVAL. The + * lseek() to 0 will fix things. */ + if (cc < 0) { + if (errno == EINVAL && + (lseek(fd, 0, SEEK_CUR) + bufsize) < 0) { + (void) lseek(fd, 0, 0); + goto again; + } + err(FATAL, "read: %s", strerror(errno)); + /* NOTREACHED */ + } + /* Loop through the packet(s) */ +#define bhp ((struct bpf_hdr *)bp) + bp = buf; + ep = bp + cc; + while (bp < ep) { + register int caplen, hdrlen; + + caplen = bhp->bh_caplen; + hdrlen = bhp->bh_hdrlen; + if (rarp_check(bp + hdrlen, caplen)) + rarp_process(ii, bp + hdrlen); + bp += BPF_WORDALIGN(hdrlen + caplen); + } + } + } +} +#ifndef TFTP_DIR +#define TFTP_DIR "/tftpboot" +#endif + +/* + * True if this server can boot the host whose IP address is 'addr'. + * This check is made by looking in the tftp directory for the + * configuration file. + */ +int +rarp_bootable(addr) + u_long addr; +{ + register struct dirent *dent; + register DIR *d; + char ipname[9]; + static DIR *dd = 0; + + (void) sprintf(ipname, "%08X", addr); + /* If directory is already open, rewind it. Otherwise, open it. */ + if (d = dd) + rewinddir(d); + else { + if (chdir(TFTP_DIR) == -1) { + err(FATAL, "chdir: %s", strerror(errno)); + /* NOTREACHED */ + } + d = opendir("."); + if (d == 0) { + err(FATAL, "opendir: %s", strerror(errno)); + /* NOTREACHED */ + } + dd = d; + } + while (dent = readdir(d)) + if (strncmp(dent->d_name, ipname, 8) == 0) + return 1; + return 0; +} +/* + * Given a list of IP addresses, 'alist', return the first address that + * is on network 'net'; 'netmask' is a mask indicating the network portion + * of the address. + */ +u_long +choose_ipaddr(alist, net, netmask) + u_long **alist; + u_long net; + u_long netmask; +{ + for (; *alist; ++alist) { + if ((**alist & netmask) == net) + return **alist; + } + return 0; +} +/* + * Answer the RARP request in 'pkt', on the interface 'ii'. 'pkt' has + * already been checked for validity. The reply is overlaid on the request. + */ +void +rarp_process(ii, pkt) + struct if_info *ii; + u_char *pkt; +{ + struct ether_header *ep; + struct hostent *hp; + u_long target_ipaddr; + char ename[256]; + struct in_addr in; + + ep = (struct ether_header *) pkt; + + if (ether_ntohost(ename, &ep->ether_shost) != 0 || + (hp = gethostbyname(ename)) == 0) + return; + + /* Choose correct address from list. */ + if (hp->h_addrtype != AF_INET) { + err(FATAL, "cannot handle non IP addresses"); + /* NOTREACHED */ + } + target_ipaddr = choose_ipaddr((u_long **) hp->h_addr_list, + ii->ii_ipaddr & ii->ii_netmask, ii->ii_netmask); + + if (target_ipaddr == 0) { + in.s_addr = ii->ii_ipaddr & ii->ii_netmask; + err(NONFATAL, "cannot find %s on net %s\n", + ename, inet_ntoa(in)); + return; + } + if (rarp_bootable(htonl(target_ipaddr))) + rarp_reply(ii, ep, target_ipaddr); +} +/* + * Lookup the ethernet address of the interface attached to the BPF + * file descriptor 'fd'; return it in 'eaddr'. + */ +void +lookup_eaddr(ifname, eaddr) + char *ifname; + u_char *eaddr; +{ + char inbuf[8192]; + struct ifconf ifc; + struct ifreq *ifr; + struct sockaddr_dl *sdl; + int fd; + int i, len; + + /* We cannot use SIOCGIFADDR on the BPF descriptor. + We must instead get all the interfaces with SIOCGIFCONF + and find the right one. */ + + /* Use datagram socket to get Ethernet address. */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + err(FATAL, "socket: %s", strerror(errno)); + /* NOTREACHED */ + } + + ifc.ifc_len = sizeof(inbuf); + ifc.ifc_buf = inbuf; + if (ioctl(fd, SIOCGIFCONF, (caddr_t)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + err(FATAL, "lookup_eaddr: SIOGIFCONF: %s", strerror(errno)); + /* NOTREACHED */ + } + ifr = ifc.ifc_req; + for (i = 0; i < ifc.ifc_len; + i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) { + len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; + sdl = (struct sockaddr_dl *)&ifr->ifr_addr; + if (sdl->sdl_family != AF_LINK || sdl->sdl_type != IFT_ETHER || + sdl->sdl_alen != 6) + continue; + if (!strncmp(ifr->ifr_name, ifname, sizeof(ifr->ifr_name))) { + bcopy((caddr_t)LLADDR(sdl), (caddr_t)eaddr, 6); + if (dflag) + fprintf(stderr, "%s: %x:%x:%x:%x:%x:%x\n", + ifr->ifr_name, eaddr[0], eaddr[1], + eaddr[2], eaddr[3], eaddr[4], eaddr[5]); + return; + } + } + + err(FATAL, "lookup_eaddr: Never saw interface `%s'!", ifname); +} +/* + * Lookup the IP address and network mask of the interface named 'ifname'. + */ +void +lookup_ipaddr(ifname, addrp, netmaskp) + char *ifname; + u_long *addrp; + u_long *netmaskp; +{ + int fd; + struct ifreq ifr; + + /* Use datagram socket to get IP address. */ + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + err(FATAL, "socket: %s", strerror(errno)); + /* NOTREACHED */ + } + (void) strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name); + if (ioctl(fd, SIOCGIFADDR, (char *) &ifr) < 0) { + err(FATAL, "SIOCGIFADDR: %s", strerror(errno)); + /* NOTREACHED */ + } + *addrp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr; + if (ioctl(fd, SIOCGIFNETMASK, (char *) &ifr) < 0) { + perror("SIOCGIFNETMASK"); + exit(1); + } + *netmaskp = ((struct sockaddr_in *) & ifr.ifr_addr)->sin_addr.s_addr; + /* If SIOCGIFNETMASK didn't work, figure out a mask from the IP + * address class. */ + if (*netmaskp == 0) + *netmaskp = ipaddrtonetmask(*addrp); + + (void) close(fd); +} +/* + * Poke the kernel arp tables with the ethernet/ip address combinataion + * given. When processing a reply, we must do this so that the booting + * host (i.e. the guy running rarpd), won't try to ARP for the hardware + * address of the guy being booted (he cannot answer the ARP). + */ +void +update_arptab(ep, ipaddr) + u_char *ep; + u_long ipaddr; +{ + int s; + struct arpreq request; + struct sockaddr_in *sin; + + request.arp_flags = 0; + sin = (struct sockaddr_in *) & request.arp_pa; + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = ipaddr; + request.arp_ha.sa_family = AF_UNSPEC; + /* This is needed #if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN, + because AF_UNSPEC is zero and the kernel assumes that a zero + sa_family means that the real sa_family value is in sa_len. */ + request.arp_ha.sa_len = 16; /* XXX */ + bcopy((char *) ep, (char *) request.arp_ha.sa_data, 6); + +#if 0 + s = socket(AF_INET, SOCK_DGRAM, 0); + if (ioctl(s, SIOCSARP, (caddr_t) & request) < 0) { + err(NONFATAL, "SIOCSARP: %s", strerror(errno)); + } + (void) close(s); +#endif +} +/* + * Build a reverse ARP packet and sent it out on the interface. + * 'ep' points to a valid ARPOP_REVREQUEST. The ARPOP_REVREPLY is built + * on top of the request, then written to the network. + * + * RFC 903 defines the ether_arp fields as follows. The following comments + * are taken (more or less) straight from this document. + * + * ARPOP_REVREQUEST + * + * arp_sha is the hardware address of the sender of the packet. + * arp_spa is undefined. + * arp_tha is the 'target' hardware address. + * In the case where the sender wishes to determine his own + * protocol address, this, like arp_sha, will be the hardware + * address of the sender. + * arp_tpa is undefined. + * + * ARPOP_REVREPLY + * + * arp_sha is the hardware address of the responder (the sender of the + * reply packet). + * arp_spa is the protocol address of the responder (see the note below). + * arp_tha is the hardware address of the target, and should be the same as + * that which was given in the request. + * arp_tpa is the protocol address of the target, that is, the desired address. + * + * Note that the requirement that arp_spa be filled in with the responder's + * protocol is purely for convenience. For instance, if a system were to use + * both ARP and RARP, then the inclusion of the valid protocol-hardware + * address pair (arp_spa, arp_sha) may eliminate the need for a subsequent + * ARP request. + */ +void +rarp_reply(ii, ep, ipaddr) + struct if_info *ii; + struct ether_header *ep; + u_long ipaddr; +{ + int n; + struct ether_arp *ap = (struct ether_arp *) (ep + 1); + int len; + + update_arptab((u_char *) & ap->arp_sha, ipaddr); + + /* Build the rarp reply by modifying the rarp request in place. */ + ep->ether_type = htons(ETHERTYPE_REVARP); + ap->ea_hdr.ar_hrd = htons(ARPHRD_ETHER); + ap->ea_hdr.ar_pro = htons(ETHERTYPE_IP); + ap->arp_op = htons(ARPOP_REVREPLY); + + bcopy((char *) &ap->arp_sha, (char *) &ep->ether_dhost, 6); + bcopy((char *) ii->ii_eaddr, (char *) &ep->ether_shost, 6); + bcopy((char *) ii->ii_eaddr, (char *) &ap->arp_sha, 6); + + bcopy((char *) &ipaddr, (char *) ap->arp_tpa, 4); + /* Target hardware is unchanged. */ + bcopy((char *) &ii->ii_ipaddr, (char *) ap->arp_spa, 4); + + len = sizeof(*ep) + sizeof(*ap); + n = write(ii->ii_fd, (char *) ep, len); + if (n != len) { + err(NONFATAL, "write: only %d of %d bytes written", n, len); + } +} +/* + * Get the netmask of an IP address. This routine is used if + * SIOCGIFNETMASK doesn't work. + */ +u_long +ipaddrtonetmask(addr) + u_long addr; +{ + if (IN_CLASSA(addr)) + return IN_CLASSA_NET; + if (IN_CLASSB(addr)) + return IN_CLASSB_NET; + if (IN_CLASSC(addr)) + return IN_CLASSC_NET; + err(FATAL, "unknown IP address class: %08X", addr); + /* NOTREACHED */ +} + +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +err(int fatal, const char *fmt,...) +#else +err(fmt, va_alist) + int fatal; + char *fmt; +va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + if (dflag) { + if (fatal) + (void) fprintf(stderr, "rarpd: error: "); + else + (void) fprintf(stderr, "rarpd: warning: "); + (void) vfprintf(stderr, fmt, ap); + (void) fprintf(stderr, "\n"); + } + vsyslog(LOG_ERR, fmt, ap); + va_end(ap); + if (fatal) + exit(1); + /* NOTREACHED */ +} + +void +#if __STDC__ +debug(const char *fmt,...) +#else +debug(fmt, va_alist) + char *fmt; +va_dcl +#endif +{ + va_list ap; + + if (dflag) { +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void) fprintf(stderr, "rarpd: "); + (void) vfprintf(stderr, fmt, ap); + va_end(ap); + (void) fprintf(stderr, "\n"); + } +} diff --git a/rbootd.tproj/Makefile b/rbootd.tproj/Makefile new file mode 100644 index 0000000..6a4e127 --- /dev/null +++ b/rbootd.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rbootd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = defs.h pathnames.h rmp.h rmp_var.h + +CFILES = bpf.c conf.c parseconf.c rbootd.c rmpproto.c utils.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rbootd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rbootd.tproj/Makefile.postamble b/rbootd.tproj/Makefile.postamble new file mode 100644 index 0000000..7ede358 --- /dev/null +++ b/rbootd.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/rbootd.tproj/Makefile.preamble b/rbootd.tproj/Makefile.preamble new file mode 100644 index 0000000..dcbd1c8 --- /dev/null +++ b/rbootd.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +-include ../Makefile.include diff --git a/rbootd.tproj/PB.project b/rbootd.tproj/PB.project new file mode 100644 index 0000000..4423a10 --- /dev/null +++ b/rbootd.tproj/PB.project @@ -0,0 +1,39 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (defs.h, pathnames.h, rmp.h, rmp_var.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (bpf.c, conf.c, parseconf.c, rbootd.c, rmpproto.c, utils.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rbootd.8); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rbootd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rbootd.tproj/bpf.c b/rbootd.tproj/bpf.c new file mode 100644 index 0000000..ed21480 --- /dev/null +++ b/rbootd.tproj/bpf.c @@ -0,0 +1,445 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: bpf.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)bpf.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" +#include "pathnames.h" + +static int BpfFd = -1; +static unsigned BpfLen = 0; +static u_char *BpfPkt = NULL; + +/* +** BpfOpen -- Open and initialize a BPF device. +** +** Parameters: +** None. +** +** Returns: +** File descriptor of opened BPF device (for select() etc). +** +** Side Effects: +** If an error is encountered, the program terminates here. +*/ +int +BpfOpen() +{ + struct ifreq ifr; + char bpfdev[32]; + int n = 0; + + /* + * Open the first available BPF device. + */ + do { + (void) sprintf(bpfdev, _PATH_BPF, n++); + BpfFd = open(bpfdev, O_RDWR); + } while (BpfFd < 0 && (errno == EBUSY || errno == EPERM)); + + if (BpfFd < 0) { + syslog(LOG_ERR, "bpf: no available devices: %m"); + Exit(0); + } + + /* + * Set interface name for bpf device, get data link layer + * type and make sure it's type Ethernet. + */ + (void) strncpy(ifr.ifr_name, IntfName, sizeof(ifr.ifr_name)); + if (ioctl(BpfFd, BIOCSETIF, (caddr_t)&ifr) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCSETIF,%s): %m", IntfName); + Exit(0); + } + + /* + * Make sure we are dealing with an Ethernet device. + */ + if (ioctl(BpfFd, BIOCGDLT, (caddr_t)&n) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCGDLT): %m"); + Exit(0); + } + if (n != DLT_EN10MB) { + syslog(LOG_ERR,"bpf: %s: data-link type %d unsupported", + IntfName, n); + Exit(0); + } + + /* + * On read(), return packets immediately (do not buffer them). + */ + n = 1; + if (ioctl(BpfFd, BIOCIMMEDIATE, (caddr_t)&n) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCIMMEDIATE): %m"); + Exit(0); + } + + /* + * Try to enable the chip/driver's multicast address filter to + * grab our RMP address. If this fails, try promiscuous mode. + * If this fails, there's no way we are going to get any RMP + * packets so just exit here. + */ +#ifdef MSG_EOR + ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; +#endif + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); + if (ioctl(BpfFd, SIOCADDMULTI, (caddr_t)&ifr) < 0) { + syslog(LOG_WARNING, + "bpf: can't add mcast addr (%m), setting promiscuous mode"); + + if (ioctl(BpfFd, BIOCPROMISC, (caddr_t)0) < 0) { + syslog(LOG_ERR, "bpf: can't set promiscuous mode: %m"); + Exit(0); + } + } + + /* + * Ask BPF how much buffer space it requires and allocate one. + */ + if (ioctl(BpfFd, BIOCGBLEN, (caddr_t)&BpfLen) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCGBLEN): %m"); + Exit(0); + } + if (BpfPkt == NULL) + BpfPkt = (u_char *)malloc(BpfLen); + + if (BpfPkt == NULL) { + syslog(LOG_ERR, "bpf: out of memory (%u bytes for bpfpkt)", + BpfLen); + Exit(0); + } + + /* + * Write a little program to snarf RMP Boot packets and stuff + * it down BPF's throat (i.e. set up the packet filter). + */ + { +#define RMP ((struct rmp_packet *)0) + static struct bpf_insn bpf_insn[] = { + { BPF_LD|BPF_B|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dsap }, + { BPF_JMP|BPF_JEQ|BPF_K, 0, 5, IEEE_DSAP_HP }, + { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.cntrl }, + { BPF_JMP|BPF_JEQ|BPF_K, 0, 3, IEEE_CNTL_HP }, + { BPF_LD|BPF_H|BPF_ABS, 0, 0, (long)&RMP->hp_llc.dxsap }, + { BPF_JMP|BPF_JEQ|BPF_K, 0, 1, HPEXT_DXSAP }, + { BPF_RET|BPF_K, 0, 0, RMP_MAX_PACKET }, + { BPF_RET|BPF_K, 0, 0, 0x0 } + }; +#undef RMP + static struct bpf_program bpf_pgm = { + sizeof(bpf_insn)/sizeof(bpf_insn[0]), bpf_insn + }; + + if (ioctl(BpfFd, BIOCSETF, (caddr_t)&bpf_pgm) < 0) { + syslog(LOG_ERR, "bpf: ioctl(BIOCSETF): %m"); + Exit(0); + } + } + + return(BpfFd); +} + +/* +** BPF GetIntfName -- Return the name of a network interface attached to +** the system, or 0 if none can be found. The interface +** must be configured up; the lowest unit number is +** preferred; loopback is ignored. +** +** Parameters: +** errmsg - if no network interface found, *errmsg explains why. +** +** Returns: +** A (static) pointer to interface name, or NULL on error. +** +** Side Effects: +** None. +*/ +char * +BpfGetIntfName(errmsg) + char **errmsg; +{ + struct ifreq ibuf[8], *ifrp, *ifend, *mp; + struct ifconf ifc; + int fd; + int minunit, n; + char *cp; + static char device[sizeof(ifrp->ifr_name)]; + static char errbuf[128] = "No Error!"; + + if (errmsg != NULL) + *errmsg = errbuf; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + (void) strcpy(errbuf, "bpf: socket: %m"); + return(NULL); + } + ifc.ifc_len = sizeof ibuf; + ifc.ifc_buf = (caddr_t)ibuf; + +#ifdef OSIOCGIFCONF + if (ioctl(fd, OSIOCGIFCONF, (char *)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + (void) strcpy(errbuf, "bpf: ioctl(OSIOCGIFCONF): %m"); + return(NULL); + } +#else + if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || + ifc.ifc_len < sizeof(struct ifreq)) { + (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFCONF): %m"); + return(NULL); + } +#endif + ifrp = ibuf; + ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); + + mp = 0; + minunit = 666; + for (; ifrp < ifend; ++ifrp) { + if (ioctl(fd, SIOCGIFFLAGS, (char *)ifrp) < 0) { + (void) strcpy(errbuf, "bpf: ioctl(SIOCGIFFLAGS): %m"); + return(NULL); + } + + /* + * If interface is down or this is the loopback interface, + * ignore it. + */ + if ((ifrp->ifr_flags & IFF_UP) == 0 || +#ifdef IFF_LOOPBACK + (ifrp->ifr_flags & IFF_LOOPBACK)) +#else + (strcmp(ifrp->ifr_name, "lo0") == 0)) +#endif + continue; + + for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) + ; + n = atoi(cp); + if (n < minunit) { + minunit = n; + mp = ifrp; + } + } + + (void) close(fd); + if (mp == 0) { + (void) strcpy(errbuf, "bpf: no interfaces found"); + return(NULL); + } + + (void) strcpy(device, mp->ifr_name); + return(device); +} + +/* +** BpfRead -- Read packets from a BPF device and fill in `rconn'. +** +** Parameters: +** rconn - filled in with next packet. +** doread - is True if we can issue a read() syscall. +** +** Returns: +** True if `rconn' contains a new packet, False otherwise. +** +** Side Effects: +** None. +*/ +int +BpfRead(rconn, doread) + RMPCONN *rconn; + int doread; +{ + register int datlen, caplen, hdrlen; + static u_char *bp = NULL, *ep = NULL; + int cc; + + /* + * The read() may block, or it may return one or more packets. + * We let the caller decide whether or not we can issue a read(). + */ + if (doread) { + if ((cc = read(BpfFd, (char *)BpfPkt, (int)BpfLen)) < 0) { + syslog(LOG_ERR, "bpf: read: %m"); + return(0); + } else { + bp = BpfPkt; + ep = BpfPkt + cc; + } + } + +#define bhp ((struct bpf_hdr *)bp) + /* + * If there is a new packet in the buffer, stuff it into `rconn' + * and return a success indication. + */ + if (bp < ep) { + datlen = bhp->bh_datalen; + caplen = bhp->bh_caplen; + hdrlen = bhp->bh_hdrlen; + + if (caplen != datlen) + syslog(LOG_ERR, + "bpf: short packet dropped (%d of %d bytes)", + caplen, datlen); + else if (caplen > sizeof(struct rmp_packet)) + syslog(LOG_ERR, "bpf: large packet dropped (%d bytes)", + caplen); + else { + rconn->rmplen = caplen; + bcopy((char *)&bhp->bh_tstamp, (char *)&rconn->tstamp, + sizeof(struct timeval)); + bcopy((char *)bp + hdrlen, (char *)&rconn->rmp, caplen); + } + bp += BPF_WORDALIGN(caplen + hdrlen); + return(1); + } +#undef bhp + + return(0); +} + +/* +** BpfWrite -- Write packet to BPF device. +** +** Parameters: +** rconn - packet to send. +** +** Returns: +** True if write succeeded, False otherwise. +** +** Side Effects: +** None. +*/ +int +BpfWrite(rconn) + RMPCONN *rconn; +{ + if (write(BpfFd, (char *)&rconn->rmp, rconn->rmplen) < 0) { + syslog(LOG_ERR, "write: %s: %m", EnetStr(rconn)); + return(0); + } + + return(1); +} + +/* +** BpfClose -- Close a BPF device. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** None. +*/ +void +BpfClose() +{ + struct ifreq ifr; + + if (BpfPkt != NULL) { + free((char *)BpfPkt); + BpfPkt = NULL; + } + + if (BpfFd == -1) + return; + +#ifdef MSG_EOR + ifr.ifr_addr.sa_len = RMP_ADDRLEN + 2; +#endif + ifr.ifr_addr.sa_family = AF_UNSPEC; + bcopy(&RmpMcastAddr[0], (char *)&ifr.ifr_addr.sa_data[0], RMP_ADDRLEN); + if (ioctl(BpfFd, SIOCDELMULTI, (caddr_t)&ifr) < 0) + (void) ioctl(BpfFd, BIOCPROMISC, (caddr_t)0); + + (void) close(BpfFd); + BpfFd = -1; +} diff --git a/rbootd.tproj/conf.c b/rbootd.tproj/conf.c new file mode 100644 index 0000000..e61a0f3 --- /dev/null +++ b/rbootd.tproj/conf.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)conf.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: conf.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)conf.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include + +#include +#include "defs.h" +#include "pathnames.h" + +/* +** Define (and possibly initialize) global variables here. +** +** Caveat: +** The maximum number of bootable files (`char *BootFiles[]') is +** limited to C_MAXFILE (i.e. the maximum number of files that +** can be spec'd in the configuration file). This was done to +** simplify the boot file search code. +*/ + +char *ProgName; /* path-stripped argv[0] */ +char MyHost[MAXHOSTNAMELEN+1]; /* host name */ +int MyPid; /* process id */ +int DebugFlg = 0; /* set true if debugging */ +int BootAny = 0; /* set true if we boot anyone */ + +char *ConfigFile = NULL; /* configuration file */ +char *DfltConfig = _PATH_RBOOTDCONF; /* default configuration file */ +char *PidFile = _PATH_RBOOTDPID; /* file w/pid of server */ +char *BootDir = _PATH_RBOOTDLIB; /* directory w/boot files */ +char *DbgFile = _PATH_RBOOTDDBG; /* debug output file */ + +FILE *DbgFp = NULL; /* debug file pointer */ +char *IntfName = NULL; /* intf we are attached to */ + +u_short SessionID = 0; /* generated session ID */ + +char *BootFiles[C_MAXFILE]; /* list of boot files */ + +CLIENT *Clients = NULL; /* list of addrs we'll accept */ +RMPCONN *RmpConns = NULL; /* list of active connections */ + +char RmpMcastAddr[RMP_ADDRLEN] = RMP_ADDR; /* RMP multicast address */ diff --git a/rbootd.tproj/defs.h b/rbootd.tproj/defs.h new file mode 100644 index 0000000..976ffc1 --- /dev/null +++ b/rbootd.tproj/defs.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: defs.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#include "rmp.h" +#include "rmp_var.h" + +/* +** Common #define's and external variables. All other files should +** include this. +*/ + +/* + * This may be defined in , if not, it's defined here. + */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +/* + * SIGUSR1 and SIGUSR2 are defined in for 4.3BSD systems. + */ +#ifndef SIGUSR1 +#define SIGUSR1 SIGEMT +#endif +#ifndef SIGUSR2 +#define SIGUSR2 SIGFPE +#endif + +/* + * These can be faster & more efficient than strcmp()/strncmp()... + */ +#define STREQN(s1,s2) ((*s1 == *s2) && (strcmp(s1,s2) == 0)) +#define STRNEQN(s1,s2,n) ((*s1 == *s2) && (strncmp(s1,s2,n) == 0)) + +/* + * Configuration file limitations. + */ +#define C_MAXFILE 10 /* max number of boot-able files */ +#define C_LINELEN 1024 /* max length of line */ + +/* + * Direction of packet (used as argument to DispPkt). + */ +#define DIR_RCVD 0 +#define DIR_SENT 1 +#define DIR_NONE 2 + +/* + * These need not be functions, so... + */ +#define FreeStr(str) free(str) +#define FreeClient(cli) free(cli) +#define GenSessID() (++SessionID ? SessionID: ++SessionID) + +/* + * Converting an Ethernet address to a string is done in many routines. + * Using `rmp.hp_hdr.saddr' works because this field is *never* changed; + * it will *always* contain the source address of the packet. + */ +#define EnetStr(rptr) GetEtherAddr(&(rptr)->rmp.hp_hdr.saddr[0]) + +/* + * Every machine we can boot will have one of these allocated for it + * (unless there are no restrictions on who we can boot). + */ +typedef struct client_s { + u_char addr[RMP_ADDRLEN]; /* addr of machine */ + char *files[C_MAXFILE]; /* boot-able files */ + struct client_s *next; /* ptr to next */ +} CLIENT; + +/* + * Every active connection has one of these allocated for it. + */ +typedef struct rmpconn_s { + struct rmp_packet rmp; /* RMP packet */ + int rmplen; /* length of packet */ + struct timeval tstamp; /* last time active */ + int bootfd; /* open boot file */ + struct rmpconn_s *next; /* ptr to next */ +} RMPCONN; + +/* + * All these variables are defined in "conf.c". + */ +extern char *ProgName; /* path-stripped argv[0] */ +extern char MyHost[]; /* this hosts' name */ +extern int MyPid; /* this processes' ID */ +extern int DebugFlg; /* set true if debugging */ +extern int BootAny; /* set true if we can boot anyone */ + +extern char *ConfigFile; /* configuration file */ +extern char *DfltConfig; /* default configuration file */ +extern char *DbgFile; /* debug output file */ +extern char *PidFile; /* file containing pid of server */ +extern char *BootDir; /* directory w/boot files */ + +extern FILE *DbgFp; /* debug file pointer */ +extern char *IntfName; /* interface we are attached to */ + +extern u_short SessionID; /* generated session ID */ + +extern char *BootFiles[]; /* list of boot files */ + +extern CLIENT *Clients; /* list of addrs we'll accept */ +extern RMPCONN *RmpConns; /* list of active connections */ + +extern char RmpMcastAddr[]; /* RMP multicast address */ + +void AddConn __P((RMPCONN *)); +int BootDone __P((RMPCONN *)); +void BpfClose __P((void)); +char *BpfGetIntfName __P((char **)); +int BpfOpen __P((void)); +int BpfRead __P((RMPCONN *, int)); +int BpfWrite __P((RMPCONN *)); +void DebugOff __P((int)); +void DebugOn __P((int)); +void DispPkt __P((RMPCONN *, int)); +void DoTimeout __P((void)); +void DspFlnm __P((u_int, char *)); +void Exit __P((int)); +CLIENT *FindClient __P((RMPCONN *)); +RMPCONN *FindConn __P((RMPCONN *)); +void FreeClients __P((void)); +void FreeConn __P((RMPCONN *)); +void FreeConns __P((void)); +int GetBootFiles __P((void)); +char *GetEtherAddr __P((u_char *)); +CLIENT *NewClient __P((u_char *)); +RMPCONN *NewConn __P((RMPCONN *)); +char *NewStr __P((char *)); +u_char *ParseAddr __P((char *)); +int ParseConfig __P((void)); +void ProcessPacket __P((RMPCONN *, CLIENT *)); +void ReConfig __P((int)); +void RemoveConn __P((RMPCONN *)); +int SendBootRepl __P((struct rmp_packet *, RMPCONN *, char *[])); +int SendFileNo __P((struct rmp_packet *, RMPCONN *, char *[])); +int SendPacket __P((RMPCONN *)); +int SendReadRepl __P((RMPCONN *)); +int SendServerID __P((RMPCONN *)); diff --git a/rbootd.tproj/parseconf.c b/rbootd.tproj/parseconf.c new file mode 100644 index 0000000..ddf2f19 --- /dev/null +++ b/rbootd.tproj/parseconf.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)parseconf.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: parseconf.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)parseconf.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" + +/* +** ParseConfig -- parse the config file into linked list of clients. +** +** Parameters: +** None. +** +** Returns: +** 1 on success, 0 otherwise. +** +** Side Effects: +** - Linked list of clients will be (re)allocated. +** +** Warnings: +** - GetBootFiles() must be called before this routine +** to create a linked list of default boot files. +*/ +int +ParseConfig() +{ + FILE *fp; + CLIENT *client; + u_char *addr; + char line[C_LINELEN]; + register char *cp, *bcp; + register int i, j; + int omask, linecnt = 0; + + if (BootAny) /* ignore config file */ + return(1); + + FreeClients(); /* delete old list of clients */ + + if ((fp = fopen(ConfigFile, "r")) == NULL) { + syslog(LOG_ERR, "ParseConfig: can't open config file (%s)", + ConfigFile); + return(0); + } + + /* + * We've got to block SIGHUP to prevent reconfiguration while + * dealing with the linked list of Clients. This can be done + * when actually linking the new client into the list, but + * this could have unexpected results if the server was HUP'd + * whilst reconfiguring. Hence, it is done here. + */ + omask = sigblock(sigmask(SIGHUP)); + + /* + * GETSTR positions `bcp' at the start of the current token, + * and null terminates it. `cp' is positioned at the start + * of the next token. spaces & commas are separators. + */ +#define GETSTR while (isspace(*cp) || *cp == ',') cp++; \ + bcp = cp; \ + while (*cp && *cp!=',' && !isspace(*cp)) cp++; \ + if (*cp) *cp++ = '\0' + + /* + * For each line, parse it into a new CLIENT struct. + */ + while (fgets(line, C_LINELEN, fp) != NULL) { + linecnt++; /* line counter */ + + if (*line == '\0' || *line == '#') /* ignore comment */ + continue; + + if ((cp = index(line,'#')) != NULL) /* trash comments */ + *cp = '\0'; + + cp = line; /* init `cp' */ + GETSTR; /* get RMP addr */ + if (bcp == cp) /* all delimiters */ + continue; + + /* + * Get an RMP address from a string. Abort on failure. + */ + if ((addr = ParseAddr(bcp)) == NULL) { + syslog(LOG_ERR, + "ParseConfig: line %d: cant parse <%s>", + linecnt, bcp); + continue; + } + + if ((client = NewClient(addr)) == NULL) /* alloc new client */ + continue; + + GETSTR; /* get first file */ + + /* + * If no boot files are spec'd, use the default list. + * Otherwise, validate each file (`bcp') against the + * list of boot-able files. + */ + i = 0; + if (bcp == cp) /* no files spec'd */ + for (; i < C_MAXFILE && BootFiles[i] != NULL; i++) + client->files[i] = BootFiles[i]; + else { + do { + /* + * For each boot file spec'd, make sure it's + * in our list. If so, include a pointer to + * it in the CLIENT's list of boot files. + */ + for (j = 0; ; j++) { + if (j==C_MAXFILE||BootFiles[j]==NULL) { + syslog(LOG_ERR, "ParseConfig: line %d: no boot file (%s)", + linecnt, bcp); + break; + } + if (STREQN(BootFiles[j], bcp)) { + if (i < C_MAXFILE) + client->files[i++] = + BootFiles[j]; + else + syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)", + linecnt, bcp); + break; + } + } + GETSTR; /* get next file */ + } while (bcp != cp); + + /* + * Restricted list of boot files were spec'd, + * however, none of them were found. Since we + * apparently cant let them boot "just anything", + * the entire record is invalidated. + */ + if (i == 0) { + FreeClient(client); + continue; + } + } + + /* + * Link this client into the linked list of clients. + * SIGHUP has already been blocked. + */ + if (Clients) + client->next = Clients; + Clients = client; + } + + (void) fclose(fp); /* close config file */ + + (void) sigsetmask(omask); /* reset signal mask */ + + return(1); /* return success */ +} + +/* +** ParseAddr -- Parse a string containing an RMP address. +** +** This routine is fairly liberal at parsing an RMP address. The +** address must contain 6 octets consisting of between 0 and 2 hex +** chars (upper/lower case) separated by colons. If two colons are +** together (e.g. "::", the octet between them is recorded as being +** zero. Hence, the following addrs are all valid and parse to the +** same thing: +** +** 08:00:09:00:66:ad 8::9:0:66:AD 8::9::66:aD +** +** For clarity, an RMP address is really an Ethernet address, but +** since the HP boot code uses IEEE 802.3, it's really an IEEE +** 802.3 address. Of course, all of these are identical. +** +** Parameters: +** str - string representation of an RMP address. +** +** Returns: +** pointer to a static array of RMP_ADDRLEN bytes. +** +** Side Effects: +** None. +** +** Warnings: +** - The return value points to a static buffer; it must +** be copied if it's to be saved. +** - For speed, we assume a u_char consists of 8 bits. +*/ +u_char * +ParseAddr(str) + char *str; +{ + static u_char addr[RMP_ADDRLEN]; + register char *cp; + register unsigned i; + register int part, subpart; + + bzero((char *)&addr[0], RMP_ADDRLEN); /* zero static buffer */ + + part = subpart = 0; + for (cp = str; *cp; cp++) { + /* + * A colon (`:') must be used to delimit each octet. + */ + if (*cp == ':') { + if (++part == RMP_ADDRLEN) /* too many parts */ + return(NULL); + subpart = 0; + continue; + } + + /* + * Convert hex character to an integer. + */ + if (isdigit(*cp)) + i = *cp - '0'; + else { + i = (isupper(*cp)? tolower(*cp): *cp) - 'a' + 10; + if (i < 10 || i > 15) /* not a hex char */ + return(NULL); + } + + if (subpart++) { + if (subpart > 2) /* too many hex chars */ + return(NULL); + addr[part] <<= 4; + } + addr[part] |= i; + } + + if (part != (RMP_ADDRLEN-1)) /* too few parts */ + return(NULL); + + return(&addr[0]); +} + +/* +** GetBootFiles -- record list of files in current (boot) directory. +** +** Parameters: +** None. +** +** Returns: +** Number of boot files on success, 0 on failure. +** +** Side Effects: +** Strings in `BootFiles' are freed/allocated. +** +** Warnings: +** - After this routine is called, ParseConfig() must be +** called to re-order it's list of boot file pointers. +*/ +int +GetBootFiles() +{ + DIR *dfd; + struct stat statb; + register struct dirent *dp; + register int i; + + /* + * Free the current list of boot files. + */ + for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) { + FreeStr(BootFiles[i]); + BootFiles[i] = NULL; + } + + /* + * Open current directory to read boot file names. + */ + if ((dfd = opendir(".")) == NULL) { /* open BootDir */ + syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)\n", + BootDir); + return(0); + } + + /* + * Read each boot file name and allocate space for it in the + * list of boot files (BootFiles). All boot files read after + * C_MAXFILE will be ignored. + */ + i = 0; + for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) { + if (stat(dp->d_name, &statb) < 0 || + (statb.st_mode & S_IFMT) != S_IFREG) + continue; + if (i == C_MAXFILE) + syslog(LOG_ERR, + "GetBootFiles: too many boot files (%s ignored)", + dp->d_name); + else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL) + i++; + } + + (void) closedir(dfd); /* close BootDir */ + + if (i == 0) /* cant find any boot files */ + syslog(LOG_ERR, "GetBootFiles: no boot files (%s)\n", BootDir); + + return(i); +} diff --git a/rbootd.tproj/pathnames.h b/rbootd.tproj/pathnames.h new file mode 100644 index 0000000..15765da --- /dev/null +++ b/rbootd.tproj/pathnames.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: pathnames.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#define _PATH_BPF "/dev/bpf%d" +#define _PATH_RBOOTDCONF "/etc/rbootd.conf" +#define _PATH_RBOOTDDBG "/tmp/rbootd.dbg" +#define _PATH_RBOOTDLIB "/usr/mdec/rbootd" +#define _PATH_RBOOTDPID "/var/run/rbootd.pid" diff --git a/rbootd.tproj/rbootd.8 b/rbootd.tproj/rbootd.8 new file mode 100644 index 0000000..f4eb364 --- /dev/null +++ b/rbootd.tproj/rbootd.8 @@ -0,0 +1,156 @@ +.\" Copyright (c) 1988, 1992 The University of Utah and the Center +.\" for Software Science (CSS). +.\" Copyright (c) 1992, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Center for Software Science of the University of Utah Computer +.\" Science Department. CSS requests users of this software to return +.\" to css-dist@cs.utah.edu any improvements that they make and grant +.\" CSS redistribution rights. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rbootd.8 8.2 (Berkeley) 12/11/93 +.\" +.\" Utah $Hdr: rbootd.man 3.1 92/07/06$ +.\" Author: Jeff Forys, University of Utah CSS +.\" +.Dd "December 11, 1993" +.Dt RBOOTD 8 +.Os +.Sh NAME +.Nm rbootd +.Nd HP remote boot server +.Sh SYNOPSIS +.Nm rbootd +.Op Fl ad +.Op Fl i Ar interface +.Op config_file +.Sh DESCRIPTION +The +.Nm rbootd +utility services boot requests from Hewlett-Packard workstations over a +local area network. +All boot files must reside in the boot file directory; further, if a +client supplies path information in its boot request, it will be silently +stripped away before processing. +By default, +.Nm rbootd +only responds to requests from machines listed in its configuration file. +.Pp +The options are as follows: +.Bl -tag -width Fl +.It Fl a +Respond to boot requests from any machine. +The configuration file is ignored if this option is specified. +.It Fl d +Run +.Nm rbootd +in debug mode. +Packets sent and received are displayed to the terminal. +.It Fl i Ar interface +Service boot requests on specified interface. +If unspecified, +.Nm rbootd +searches the system interface list for the lowest numbered, configured +``up'' interface (excluding loopback). +Ties are broken by choosing the earliest match. +.El +.Pp +Specifying +.Ar config_file +on the command line causes +.Nm rbootd +to use a different configuration file from the default. +.Pp +The configuration file is a text file where each line describes a particular +machine. +A line must start with a machine's Ethernet address followed by an optional +list of boot file names. +An Ethernet address is specified in hexadecimal with each of its six octets +separated by a colon. +The boot file names come from the boot file directory. +The ethernet address and boot file(s) must be separated by white-space +and/or comma characters. +A pound sign causes the remainder of a line to be ignored. +.Pp +Here is a sample configuration file: +.Bl -column 08:00:09:0:66:ad SYSHPBSD,SYSHPUX "# vandy (anything)" +.It # +.It # ethernet addr boot file(s) comments +.It # +.It 08:00:09:0:66:ad SYSHPBSD # snake (4.3BSD) +.It 08:00:09:0:59:5b # vandy (anything) +.It 8::9:1:C6:75 SYSHPBSD,SYSHPUX # jaguar (either) +.El +.Pp +.Nm Rbootd +logs status and error messages via +.Xr syslog 3 . +A startup message is always logged, and in the case of fatal errors (or +deadly signals) a message is logged announcing the server's termination. +In general, a non-fatal error is handled by ignoring the event that caused +it (e.g. an invalid Ethernet address in the config file causes that line +to be invalidated). +.Pp +The following signals have the specified effect when sent to the server +process using the +.Xr kill 1 +command: +.Bl -tag -width SIGUSR1 -offset -compact +.It SIGHUP +Drop all active connections and reconfigure. +.It SIGUSR1 +Turn on debugging, do nothing if already on. +.It SIGUSR2 +Turn off debugging, do nothing if already off. +.El +.Sh "FILES" +.Bl -tag -width /usr/libexec/rbootd -compact +.It /dev/bpf# +packet-filter device +.It /etc/rbootd.conf +configuration file +.It /tmp/rbootd.dbg +debug output +.It /usr/mdec/rbootd +directory containing boot files +.It /var/run/rbootd.pid +process id +.El +.Sh SEE ALSO +.Xr kill 1 , +.Xr socket 2 , +.Xr signal 3 , +.Xr syslog 3 , +.Xr rmp 4 +.Sh BUGS +If multiple servers are started on the same interface, each will receive +and respond to the same boot packets. diff --git a/rbootd.tproj/rbootd.c b/rbootd.tproj/rbootd.c new file mode 100644 index 0000000..cf661b2 --- /dev/null +++ b/rbootd.tproj/rbootd.c @@ -0,0 +1,531 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rbootd.c 8.2 (Berkeley) 2/22/94 + * + * Utah $Hdr: rbootd.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1992, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rbootd.c 8.2 (Berkeley) 2/22/94"; +#endif /* not lint */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" + + +/* fd mask macros (backward compatibility with 4.2BSD) */ +#ifndef FD_SET +#ifdef notdef +typedef struct fd_set { /* this should already be in 4.2 */ + int fds_bits[1]; +} fd_set; +#endif +#define FD_ZERO(p) ((p)->fds_bits[0] = 0) +#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n))) +#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1 << (n))) +#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n))) +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int c, fd, omask, maxfds; + fd_set rset; + + /* + * Find what name we are running under. + */ + ProgName = (ProgName = rindex(argv[0],'/')) ? ++ProgName : *argv; + + /* + * Close any open file descriptors. + * Temporarily leave stdin & stdout open for `-d', + * and stderr open for any pre-syslog error messages. + */ + { + int i, nfds = getdtablesize(); + + for (i = 0; i < nfds; i++) + if (i != fileno(stdin) && i != fileno(stdout) && + i != fileno(stderr)) + (void) close(i); + } + + /* + * Parse any arguments. + */ + while ((c = getopt(argc, argv, "adi:")) != EOF) + switch(c) { + case 'a': + BootAny++; + break; + case 'd': + DebugFlg++; + break; + case 'i': + IntfName = optarg; + break; + } + for (; optind < argc; optind++) { + if (ConfigFile == NULL) + ConfigFile = argv[optind]; + else { + fprintf(stderr, + "%s: too many config files (`%s' ignored)\n", + ProgName, argv[optind]); + } + } + + if (ConfigFile == NULL) /* use default config file */ + ConfigFile = DfltConfig; + + if (DebugFlg) { + DbgFp = stdout; /* output to stdout */ + + (void) signal(SIGUSR1, SIG_IGN); /* dont muck w/DbgFp */ + (void) signal(SIGUSR2, SIG_IGN); + } else { + (void) fclose(stdin); /* dont need these */ + (void) fclose(stdout); + + /* + * Fork off a child to do the work & exit. + */ + switch(fork()) { + case -1: /* fork failed */ + fprintf(stderr, "%s: ", ProgName); + perror("fork"); + Exit(0); + case 0: /* this is the CHILD */ + break; + default: /* this is the PARENT */ + _exit(0); + } + + /* + * Try to disassociate from the current tty. + */ + { + char *devtty = "/dev/tty"; + int i; + + if ((i = open(devtty, O_RDWR)) < 0) { + /* probably already disassociated */ + if (setpgrp(0, 0) < 0) { + fprintf(stderr, "%s: ", ProgName); + perror("setpgrp"); + } + } else { + if (ioctl(i, (u_long)TIOCNOTTY, (char *)0) < 0){ + fprintf(stderr, "%s: ", ProgName); + perror("ioctl"); + } + (void) close(i); + } + } + + (void) signal(SIGUSR1, DebugOn); + (void) signal(SIGUSR2, DebugOff); + } + + (void) fclose(stderr); /* finished with it */ + +#ifdef SYSLOG4_2 + openlog(ProgName, LOG_PID); +#else + openlog(ProgName, LOG_PID, LOG_DAEMON); +#endif + + /* + * If no interface was specified, get one now. + * + * This is convoluted because we want to get the default interface + * name for the syslog("restarted") message. If BpfGetIntfName() + * runs into an error, it will return a syslog-able error message + * (in `errmsg') which will be displayed here. + */ + if (IntfName == NULL) { + char *errmsg; + + if ((IntfName = BpfGetIntfName(&errmsg)) == NULL) { + syslog(LOG_NOTICE, "restarted (??)"); + syslog(LOG_ERR, errmsg); + Exit(0); + } + } + + syslog(LOG_NOTICE, "restarted (%s)", IntfName); + + (void) signal(SIGHUP, ReConfig); + (void) signal(SIGINT, Exit); + (void) signal(SIGTERM, Exit); + + /* + * Grab our host name and pid. + */ + if (gethostname(MyHost, MAXHOSTNAMELEN) < 0) { + syslog(LOG_ERR, "gethostname: %m"); + Exit(0); + } + MyHost[MAXHOSTNAMELEN] = '\0'; + + MyPid = getpid(); + + /* + * Write proc's pid to a file. + */ + { + FILE *fp; + + if ((fp = fopen(PidFile, "w")) != NULL) { + (void) fprintf(fp, "%d\n", MyPid); + (void) fclose(fp); + } else { + syslog(LOG_WARNING, "fopen: failed (%s)", PidFile); + } + } + + /* + * All boot files are relative to the boot directory, we might + * as well chdir() there to make life easier. + */ + if (chdir(BootDir) < 0) { + syslog(LOG_ERR, "chdir: %m (%s)", BootDir); + Exit(0); + } + + /* + * Initial configuration. + */ + omask = sigblock(sigmask(SIGHUP)); /* prevent reconfig's */ + if (GetBootFiles() == 0) /* get list of boot files */ + Exit(0); + if (ParseConfig() == 0) /* parse config file */ + Exit(0); + + /* + * Open and initialize a BPF device for the appropriate interface. + * If an error is encountered, a message is displayed and Exit() + * is called. + */ + fd = BpfOpen(); + + (void) sigsetmask(omask); /* allow reconfig's */ + + /* + * Main loop: receive a packet, determine where it came from, + * and if we service this host, call routine to handle request. + */ + maxfds = fd + 1; + FD_ZERO(&rset); + FD_SET(fd, &rset); + for (;;) { + struct timeval timeout; + fd_set r; + int nsel; + + r = rset; + + if (RmpConns == NULL) { /* timeout isnt necessary */ + nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0, + (struct timeval *)0); + } else { + timeout.tv_sec = RMP_TIMEOUT; + timeout.tv_usec = 0; + nsel = select(maxfds, &r, (fd_set *)0, (fd_set *)0, + &timeout); + } + + if (nsel < 0) { + if (errno == EINTR) + continue; + syslog(LOG_ERR, "select: %m"); + Exit(0); + } else if (nsel == 0) { /* timeout */ + DoTimeout(); /* clear stale conns */ + continue; + } + + if (FD_ISSET(fd, &r)) { + RMPCONN rconn; + CLIENT *client, *FindClient(); + int doread = 1; + + while (BpfRead(&rconn, doread)) { + doread = 0; + + if (DbgFp != NULL) /* display packet */ + DispPkt(&rconn,DIR_RCVD); + + omask = sigblock(sigmask(SIGHUP)); + + /* + * If we do not restrict service, set the + * client to NULL (ProcessPacket() handles + * this). Otherwise, check that we can + * service this host; if not, log a message + * and ignore the packet. + */ + if (BootAny) { + client = NULL; + } else if ((client=FindClient(&rconn))==NULL) { + syslog(LOG_INFO, + "%s: boot packet ignored", + EnetStr(&rconn)); + (void) sigsetmask(omask); + continue; + } + + ProcessPacket(&rconn,client); + + (void) sigsetmask(omask); + } + } + } +} + +/* +** DoTimeout -- Free any connections that have timed out. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Timed out connections in `RmpConns' will be freed. +*/ +void +DoTimeout() +{ + register RMPCONN *rtmp; + struct timeval now; + + (void) gettimeofday(&now, (struct timezone *)0); + + /* + * For each active connection, if RMP_TIMEOUT seconds have passed + * since the last packet was sent, delete the connection. + */ + for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next) + if ((rtmp->tstamp.tv_sec + RMP_TIMEOUT) < now.tv_sec) { + syslog(LOG_WARNING, "%s: connection timed out (%u)", + EnetStr(rtmp), rtmp->rmp.r_type); + RemoveConn(rtmp); + } +} + +/* +** FindClient -- Find client associated with a packet. +** +** Parameters: +** rconn - the new packet. +** +** Returns: +** Pointer to client info if found, NULL otherwise. +** +** Side Effects: +** None. +** +** Warnings: +** - This routine must be called with SIGHUP blocked since +** a reconfigure can invalidate the information returned. +*/ + +CLIENT * +FindClient(rconn) + register RMPCONN *rconn; +{ + register CLIENT *ctmp; + + for (ctmp = Clients; ctmp != NULL; ctmp = ctmp->next) + if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0], + (char *)&ctmp->addr[0], RMP_ADDRLEN) == 0) + break; + + return(ctmp); +} + +/* +** Exit -- Log an error message and exit. +** +** Parameters: +** sig - caught signal (or zero if not dying on a signal). +** +** Returns: +** Does not return. +** +** Side Effects: +** - This process ceases to exist. +*/ +void +Exit(sig) + int sig; +{ + if (sig > 0) + syslog(LOG_ERR, "going down on signal %d", sig); + else + syslog(LOG_ERR, "going down with fatal error"); + BpfClose(); + exit(1); +} + +/* +** ReConfig -- Get new list of boot files and reread config files. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - All active connections are dropped. +** - List of boot-able files is changed. +** - List of clients is changed. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +ReConfig(signo) + int signo; +{ + syslog(LOG_NOTICE, "reconfiguring boot server"); + + FreeConns(); + + if (GetBootFiles() == 0) + Exit(0); + + if (ParseConfig() == 0) + Exit(0); +} + +/* +** DebugOff -- Turn off debugging. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Debug file is closed. +*/ +void +DebugOff(signo) + int signo; +{ + if (DbgFp != NULL) + (void) fclose(DbgFp); + + DbgFp = NULL; +} + +/* +** DebugOn -- Turn on debugging. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Debug file is opened/truncated if not already opened, +** otherwise do nothing. +*/ +void +DebugOn(signo) + int signo; +{ + if (DbgFp == NULL) { + if ((DbgFp = fopen(DbgFile, "w")) == NULL) + syslog(LOG_ERR, "can't open debug file (%s)", DbgFile); + } +} diff --git a/rbootd.tproj/rmp.h b/rbootd.tproj/rmp.h new file mode 100644 index 0000000..31b9440 --- /dev/null +++ b/rbootd.tproj/rmp.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rmp.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: rmp.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +/* + * Define MIN/MAX sizes of RMP (ethernet) packet. + * For ease of computation, the 4 octet CRC field is not included. + * + * MCLBYTES is for bpfwrite(); it is adamant about using a cluster. + */ + +#define RMP_MAX_PACKET MIN(1514,MCLBYTES) +#define RMP_MIN_PACKET 60 + +/* + * Define RMP/Ethernet Multicast address (9:0:9:0:0:4) and its length. + */ +#define RMP_ADDR { 0x9, 0x0, 0x9, 0x0, 0x0, 0x4 } +#define RMP_ADDRLEN 6 + +/* + * Define IEEE802.2 (Logical Link Control) information. + */ +#define IEEE_DSAP_HP 0xF8 /* Destination Service Access Point */ +#define IEEE_SSAP_HP 0xF8 /* Source Service Access Point */ +#define IEEE_CNTL_HP 0x0300 /* Type 1 / I format control information */ + +#define HPEXT_DXSAP 0x608 /* HP Destination Service Access Point */ +#define HPEXT_SXSAP 0x609 /* HP Source Service Access Point */ + +/* + * 802.3-style "Ethernet" header. + */ + +struct hp_hdr { + u_char daddr[RMP_ADDRLEN]; + u_char saddr[RMP_ADDRLEN]; + u_short len; +}; + +/* + * HP uses 802.2 LLC with their own local extensions. This struct makes + * sence out of this data (encapsulated in the above 802.3 packet). + */ + +struct hp_llc { + u_char dsap; /* 802.2 DSAP */ + u_char ssap; /* 802.2 SSAP */ + u_short cntrl; /* 802.2 control field */ + u_short filler; /* HP filler (must be zero) */ + u_short dxsap; /* HP extended DSAP */ + u_short sxsap; /* HP extended SSAP */ +}; diff --git a/rbootd.tproj/rmp_var.h b/rbootd.tproj/rmp_var.h new file mode 100644 index 0000000..adecc85 --- /dev/null +++ b/rbootd.tproj/rmp_var.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rmp_var.h 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: rmp_var.h 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +/* + * Possible values for "rmp_type" fields. + */ + +#define RMP_BOOT_REQ 1 /* boot request packet */ +#define RMP_BOOT_REPL 129 /* boot reply packet */ +#define RMP_READ_REQ 2 /* read request packet */ +#define RMP_READ_REPL 130 /* read reply packet */ +#define RMP_BOOT_DONE 3 /* boot complete packet */ + +/* + * Useful constants. + */ + +#define RMP_VERSION 2 /* protocol version */ +#define RMP_TIMEOUT 600 /* timeout connection after ten minutes */ +#define RMP_PROBESID 0xffff /* session ID for probes */ +#define RMP_HOSTLEN 13 /* max length of server's name */ +#define RMP_MACHLEN 20 /* length of machine type field */ + +/* + * RMP error codes + */ + +#define RMP_E_OKAY 0 +#define RMP_E_EOF 2 /* read reply: returned end of file */ +#define RMP_E_ABORT 3 /* abort operation */ +#define RMP_E_BUSY 4 /* boot reply: server busy */ +#define RMP_E_TIMEOUT 5 /* lengthen time out (not implemented) */ +#define RMP_E_NOFILE 16 /* boot reply: file does not exist */ +#define RMP_E_OPENFILE 17 /* boot reply: file open failed */ +#define RMP_E_NODFLT 18 /* boot reply: default file does not exist */ +#define RMP_E_OPENDFLT 19 /* boot reply: default file open failed */ +#define RMP_E_BADSID 25 /* read reply: bad session ID */ +#define RMP_E_BADPACKET 27 /* Bad packet detected */ + +/* + * RMPDATALEN is the maximum number of data octets that can be stuffed + * into an RMP packet. This excludes the 802.2 LLC w/HP extensions. + */ +#define RMPDATALEN (RMP_MAX_PACKET - (sizeof(struct hp_hdr) + \ + sizeof(struct hp_llc))) + +/* + * Define sizes of packets we send. Boot and Read replies are variable + * in length depending on the length of `s'. + * + * Also, define how much space `restofpkt' can take up for outgoing + * Boot and Read replies. Boot Request packets are effectively + * limited to 255 bytes due to the preceding 1-byte length field. + */ + +#define RMPBOOTSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \ + sizeof(struct rmp_boot_repl) + s - sizeof(restofpkt)) +#define RMPREADSIZE(s) (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \ + sizeof(struct rmp_read_repl) + s - sizeof(restofpkt) \ + - sizeof(u_char)) +#define RMPDONESIZE (sizeof(struct hp_hdr) + sizeof(struct hp_llc) + \ + sizeof(struct rmp_boot_done)) +#define RMPBOOTDATA 255 +#define RMPREADDATA (RMPDATALEN - \ + (2*sizeof(u_char)+sizeof(u_short)+sizeof(u_word))) + +/* + * This protocol defines some field sizes as "rest of ethernet packet". + * There is no easy way to specify this in C, so we use a one character + * field to denote it, and index past it to the end of the packet. + */ + +typedef char restofpkt; + +/* + * Due to the RMP packet layout, we'll run into alignment problems + * on machines that cant access words on half-word boundaries. If + * you know that your machine does not suffer from this problem, + * add it to the hp300 #define below. + * + * The following macros are used to deal with this problem: + * WORDZE(w) Return True if u_word `w' is zero, False otherwise. + * ZEROWORD(w) Set u_word `w' to zero. + * COPYWORD(w1,w2) Copy u_word `w1' to `w2'. + * GETWORD(w,i) Copy u_word `w' into int `i'. + * PUTWORD(i,w) Copy int `i' into u_word `w'. + * + * N.B. We do not support little endian alignment-challenged machines. + */ +#if defined(vax) || defined(tahoe) || defined(hp300) + +typedef u_int u_word; + +#define WORDZE(w) ((w) == 0) +#define ZEROWORD(w) (w) = 0 +#define COPYWORD(w1,w2) (w2) = (w1) +#define GETWORD(w, i) (i) = (w) +#define PUTWORD(i, w) (w) = (i) + +#else + +#define _WORD_HIGHPART 0 /* XXX: assume Big Endian for now */ +#define _WORD_LOWPART 1 + +typedef struct _uword { u_short val[2]; } u_word; + +#define WORDZE(w) \ + ((w.val[_WORD_HIGHPART] == 0) && (w.val[_WORD_LOWPART] == 0)) +#define ZEROWORD(w) \ + (w).val[_WORD_HIGHPART] = (w).val[_WORD_LOWPART] = 0 +#define COPYWORD(w1, w2) \ + { (w2).val[_WORD_HIGHPART] = (w1).val[_WORD_HIGHPART]; \ + (w2).val[_WORD_LOWPART] = (w1).val[_WORD_LOWPART]; \ + } +#define GETWORD(w, i) \ + (i) = (((u_int)(w).val[_WORD_HIGHPART]) << 16) | (w).val[_WORD_LOWPART] +#define PUTWORD(i, w) \ + { (w).val[_WORD_HIGHPART] = (u_short) (((i) >> 16) & 0xffff); \ + (w).val[_WORD_LOWPART] = (u_short) (i & 0xffff); \ + } + +#endif + +/* + * Packet structures. + */ + +struct rmp_raw { /* generic RMP packet */ + u_char rmp_type; /* packet type */ + u_char rmp_rawdata[RMPDATALEN-1]; +}; + +struct rmp_boot_req { /* boot request */ + u_char rmp_type; /* packet type (RMP_BOOT_REQ) */ + u_char rmp_retcode; /* return code (0) */ + u_word rmp_seqno; /* sequence number (real time clock) */ + u_short rmp_session; /* session id (normally 0) */ + u_short rmp_version; /* protocol version (RMP_VERSION) */ + char rmp_machtype[RMP_MACHLEN]; /* machine type */ + u_char rmp_flnmsize; /* length of rmp_flnm */ + restofpkt rmp_flnm; /* name of file to be read */ +}; + +struct rmp_boot_repl { /* boot reply */ + u_char rmp_type; /* packet type (RMP_BOOT_REPL) */ + u_char rmp_retcode; /* return code (normally 0) */ + u_word rmp_seqno; /* sequence number (from boot req) */ + u_short rmp_session; /* session id (generated) */ + u_short rmp_version; /* protocol version (RMP_VERSION) */ + u_char rmp_flnmsize; /* length of rmp_flnm */ + restofpkt rmp_flnm; /* name of file (from boot req) */ +}; + +struct rmp_read_req { /* read request */ + u_char rmp_type; /* packet type (RMP_READ_REQ) */ + u_char rmp_retcode; /* return code (0) */ + u_word rmp_offset; /* file relative byte offset */ + u_short rmp_session; /* session id (from boot repl) */ + u_short rmp_size; /* max no of bytes to send */ +}; + +struct rmp_read_repl { /* read reply */ + u_char rmp_type; /* packet type (RMP_READ_REPL) */ + u_char rmp_retcode; /* return code (normally 0) */ + u_word rmp_offset; /* byte offset (from read req) */ + u_short rmp_session; /* session id (from read req) */ + restofpkt rmp_data; /* data (max size from read req) */ + u_char rmp_unused; /* padding to 16-bit boundary */ +}; + +struct rmp_boot_done { /* boot complete */ + u_char rmp_type; /* packet type (RMP_BOOT_DONE) */ + u_char rmp_retcode; /* return code (0) */ + u_word rmp_unused; /* not used (0) */ + u_short rmp_session; /* session id (from read repl) */ +}; + +struct rmp_packet { + struct hp_hdr hp_hdr; + struct hp_llc hp_llc; + union { + struct rmp_boot_req rmp_brq; /* boot request */ + struct rmp_boot_repl rmp_brpl; /* boot reply */ + struct rmp_read_req rmp_rrq; /* read request */ + struct rmp_read_repl rmp_rrpl; /* read reply */ + struct rmp_boot_done rmp_done; /* boot complete */ + struct rmp_raw rmp_raw; /* raw data */ + } rmp_proto; +}; + +/* + * Make life easier... + */ + +#define r_type rmp_proto.rmp_raw.rmp_type +#define r_data rmp_proto.rmp_raw.rmp_data +#define r_brq rmp_proto.rmp_brq +#define r_brpl rmp_proto.rmp_brpl +#define r_rrq rmp_proto.rmp_rrq +#define r_rrpl rmp_proto.rmp_rrpl +#define r_done rmp_proto.rmp_done diff --git a/rbootd.tproj/rmpproto.c b/rbootd.tproj/rmpproto.c new file mode 100644 index 0000000..d8f676c --- /dev/null +++ b/rbootd.tproj/rmpproto.c @@ -0,0 +1,616 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)rmpproto.c 8.1 (Berkeley) 6/4/93 + * + * Utah $Hdr: rmpproto.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)rmpproto.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include "defs.h" + +/* +** ProcessPacket -- determine packet type and do what's required. +** +** An RMP BOOT packet has been received. Look at the type field +** and process Boot Requests, Read Requests, and Boot Complete +** packets. Any other type will be dropped with a warning msg. +** +** Parameters: +** rconn - the new connection +** client - list of files available to this host +** +** Returns: +** Nothing. +** +** Side Effects: +** - If this is a valid boot request, it will be added to +** the linked list of outstanding requests (RmpConns). +** - If this is a valid boot complete, its associated +** entry in RmpConns will be deleted. +** - Also, unless we run out of memory, a reply will be +** sent to the host that sent the packet. +*/ +void +ProcessPacket(rconn, client) + RMPCONN *rconn; + CLIENT *client; +{ + struct rmp_packet *rmp; + RMPCONN *rconnout; + + rmp = &rconn->rmp; /* cache pointer to RMP packet */ + + switch(rmp->r_type) { /* do what we came here to do */ + case RMP_BOOT_REQ: /* boot request */ + if ((rconnout = NewConn(rconn)) == NULL) + return; + + /* + * If the Session ID is 0xffff, this is a "probe" + * packet and we do not want to add the connection + * to the linked list of active connections. There + * are two types of probe packets, if the Sequence + * Number is 0 they want to know our host name, o/w + * they want the name of the file associated with + * the number spec'd by the Sequence Number. + * + * If this is an actual boot request, open the file + * and send a reply. If SendBootRepl() does not + * return 0, add the connection to the linked list + * of active connections, otherwise delete it since + * an error was encountered. + */ + if (rmp->r_brq.rmp_session == RMP_PROBESID) { + if (WORDZE(rmp->r_brq.rmp_seqno)) + (void) SendServerID(rconnout); + else + (void) SendFileNo(rmp, rconnout, + client? client->files: + BootFiles); + FreeConn(rconnout); + } else { + if (SendBootRepl(rmp, rconnout, + client? client->files: BootFiles)) + AddConn(rconnout); + else + FreeConn(rconnout); + } + break; + + case RMP_BOOT_REPL: /* boot reply (not valid) */ + syslog(LOG_WARNING, "%s: sent a boot reply", + EnetStr(rconn)); + break; + + case RMP_READ_REQ: /* read request */ + /* + * Send a portion of the boot file. + */ + (void) SendReadRepl(rconn); + break; + + case RMP_READ_REPL: /* read reply (not valid) */ + syslog(LOG_WARNING, "%s: sent a read reply", + EnetStr(rconn)); + break; + + case RMP_BOOT_DONE: /* boot complete */ + /* + * Remove the entry from the linked list of active + * connections. + */ + (void) BootDone(rconn); + break; + + default: /* unknown RMP packet type */ + syslog(LOG_WARNING, "%s: unknown packet type (%u)", + EnetStr(rconn), rmp->r_type); + } +} + +/* +** SendServerID -- send our host name to who ever requested it. +** +** Parameters: +** rconn - the reply packet to be formatted. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendServerID(rconn) + RMPCONN *rconn; +{ + register struct rmp_packet *rpl; + register char *src, *dst; + register u_char *size; + + rpl = &rconn->rmp; /* cache ptr to RMP packet */ + + /* + * Set up assorted fields in reply packet. + */ + rpl->r_brpl.rmp_type = RMP_BOOT_REPL; + rpl->r_brpl.rmp_retcode = RMP_E_OKAY; + ZEROWORD(rpl->r_brpl.rmp_seqno); + rpl->r_brpl.rmp_session = 0; + rpl->r_brpl.rmp_version = RMP_VERSION; + + size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of host name */ + + /* + * Copy our host name into the reply packet incrementing the + * length as we go. Stop at RMP_HOSTLEN or the first dot. + */ + src = MyHost; + dst = (char *) &rpl->r_brpl.rmp_flnm; + for (*size = 0; *size < RMP_HOSTLEN; (*size)++) { + if (*src == '.' || *src == '\0') + break; + *dst++ = *src++; + } + + rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ + + return(SendPacket(rconn)); /* send packet */ +} + +/* +** SendFileNo -- send the name of a bootable file to the requester. +** +** Parameters: +** req - RMP BOOT packet containing the request. +** rconn - the reply packet to be formatted. +** filelist - list of files available to the requester. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendFileNo(req, rconn, filelist) + struct rmp_packet *req; + RMPCONN *rconn; + char *filelist[]; +{ + register struct rmp_packet *rpl; + register char *src, *dst; + register u_char *size, i; + + GETWORD(req->r_brpl.rmp_seqno, i); /* SeqNo is really FileNo */ + rpl = &rconn->rmp; /* cache ptr to RMP packet */ + + /* + * Set up assorted fields in reply packet. + */ + rpl->r_brpl.rmp_type = RMP_BOOT_REPL; + PUTWORD(i, rpl->r_brpl.rmp_seqno); + i--; + rpl->r_brpl.rmp_session = 0; + rpl->r_brpl.rmp_version = RMP_VERSION; + + size = &rpl->r_brpl.rmp_flnmsize; /* ptr to length of filename */ + *size = 0; /* init length to zero */ + + /* + * Copy the file name into the reply packet incrementing the + * length as we go. Stop at end of string or when RMPBOOTDATA + * characters have been copied. Also, set return code to + * indicate success or "no more files". + */ + if (i < C_MAXFILE && filelist[i] != NULL) { + src = filelist[i]; + dst = (char *)&rpl->r_brpl.rmp_flnm; + for (; *src && *size < RMPBOOTDATA; (*size)++) { + if (*src == '\0') + break; + *dst++ = *src++; + } + rpl->r_brpl.rmp_retcode = RMP_E_OKAY; + } else + rpl->r_brpl.rmp_retcode = RMP_E_NODFLT; + + rconn->rmplen = RMPBOOTSIZE(*size); /* set packet length */ + + return(SendPacket(rconn)); /* send packet */ +} + +/* +** SendBootRepl -- open boot file and respond to boot request. +** +** Parameters: +** req - RMP BOOT packet containing the request. +** rconn - the reply packet to be formatted. +** filelist - list of files available to the requester. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendBootRepl(req, rconn, filelist) + struct rmp_packet *req; + RMPCONN *rconn; + char *filelist[]; +{ + int retval; + char *filename, filepath[RMPBOOTDATA+1]; + RMPCONN *oldconn; + register struct rmp_packet *rpl; + register char *src, *dst1, *dst2; + register u_char i; + + /* + * If another connection already exists, delete it since we + * are obviously starting again. + */ + if ((oldconn = FindConn(rconn)) != NULL) { + syslog(LOG_WARNING, "%s: dropping existing connection", + EnetStr(oldconn)); + RemoveConn(oldconn); + } + + rpl = &rconn->rmp; /* cache ptr to RMP packet */ + + /* + * Set up assorted fields in reply packet. + */ + rpl->r_brpl.rmp_type = RMP_BOOT_REPL; + COPYWORD(req->r_brq.rmp_seqno, rpl->r_brpl.rmp_seqno); + rpl->r_brpl.rmp_session = GenSessID(); + rpl->r_brpl.rmp_version = RMP_VERSION; + rpl->r_brpl.rmp_flnmsize = req->r_brq.rmp_flnmsize; + + /* + * Copy file name to `filepath' string, and into reply packet. + */ + src = &req->r_brq.rmp_flnm; + dst1 = filepath; + dst2 = &rpl->r_brpl.rmp_flnm; + for (i = 0; i < req->r_brq.rmp_flnmsize; i++) + *dst1++ = *dst2++ = *src++; + *dst1 = '\0'; + + /* + * If we are booting HP-UX machines, their secondary loader will + * ask for files like "/hp-ux". As a security measure, we do not + * allow boot files to lay outside the boot directory (unless they + * are purposely link'd out. So, make `filename' become the path- + * stripped file name and spoof the client into thinking that it + * really got what it wanted. + */ + filename = (filename = rindex(filepath,'/'))? ++filename: filepath; + + /* + * Check that this is a valid boot file name. + */ + for (i = 0; i < C_MAXFILE && filelist[i] != NULL; i++) + if (STREQN(filename, filelist[i])) + goto match; + + /* + * Invalid boot file name, set error and send reply packet. + */ + rpl->r_brpl.rmp_retcode = RMP_E_NOFILE; + retval = 0; + goto sendpkt; + +match: + /* + * This is a valid boot file. Open the file and save the file + * descriptor associated with this connection and set success + * indication. If the file couldnt be opened, set error: + * "no such file or dir" - RMP_E_NOFILE + * "file table overflow" - RMP_E_BUSY + * "too many open files" - RMP_E_BUSY + * anything else - RMP_E_OPENFILE + */ + if ((rconn->bootfd = open(filename, O_RDONLY, 0600)) < 0) { + rpl->r_brpl.rmp_retcode = (errno == ENOENT)? RMP_E_NOFILE: + (errno == EMFILE || errno == ENFILE)? RMP_E_BUSY: + RMP_E_OPENFILE; + retval = 0; + } else { + rpl->r_brpl.rmp_retcode = RMP_E_OKAY; + retval = 1; + } + +sendpkt: + syslog(LOG_INFO, "%s: request to boot %s (%s)", + EnetStr(rconn), filename, retval? "granted": "denied"); + + rconn->rmplen = RMPBOOTSIZE(rpl->r_brpl.rmp_flnmsize); + + return (retval & SendPacket(rconn)); +} + +/* +** SendReadRepl -- send a portion of the boot file to the requester. +** +** Parameters: +** rconn - the reply packet to be formatted. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendReadRepl(rconn) + RMPCONN *rconn; +{ + int retval; + RMPCONN *oldconn; + register struct rmp_packet *rpl, *req; + register int size = 0; + int madeconn = 0; + + /* + * Find the old connection. If one doesnt exist, create one only + * to return the error code. + */ + if ((oldconn = FindConn(rconn)) == NULL) { + if ((oldconn = NewConn(rconn)) == NULL) + return(0); + syslog(LOG_ERR, "SendReadRepl: no active connection (%s)", + EnetStr(rconn)); + madeconn++; + } + + req = &rconn->rmp; /* cache ptr to request packet */ + rpl = &oldconn->rmp; /* cache ptr to reply packet */ + + if (madeconn) { /* no active connection above; abort */ + rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; + retval = 1; + goto sendpkt; + } + + /* + * Make sure Session ID's match. + */ + if (req->r_rrq.rmp_session != + ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session: + rpl->r_rrpl.rmp_session)) { + syslog(LOG_ERR, "SendReadRepl: bad session id (%s)", + EnetStr(rconn)); + rpl->r_rrpl.rmp_retcode = RMP_E_BADSID; + retval = 1; + goto sendpkt; + } + + /* + * If the requester asks for more data than we can fit, + * silently clamp the request size down to RMPREADDATA. + * + * N.B. I do not know if this is "legal", however it seems + * to work. This is necessary for bpfwrite() on machines + * with MCLBYTES less than 1514. + */ + if (req->r_rrq.rmp_size > RMPREADDATA) + req->r_rrq.rmp_size = RMPREADDATA; + + /* + * Position read head on file according to info in request packet. + */ + GETWORD(req->r_rrq.rmp_offset, size); + if (lseek(oldconn->bootfd, (off_t)size, L_SET) < 0) { + syslog(LOG_ERR, "SendReadRepl: lseek: %m (%s)", + EnetStr(rconn)); + rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; + retval = 1; + goto sendpkt; + } + + /* + * Read data directly into reply packet. + */ + if ((size = read(oldconn->bootfd, &rpl->r_rrpl.rmp_data, + (int) req->r_rrq.rmp_size)) <= 0) { + if (size < 0) { + syslog(LOG_ERR, "SendReadRepl: read: %m (%s)", + EnetStr(rconn)); + rpl->r_rrpl.rmp_retcode = RMP_E_ABORT; + } else { + rpl->r_rrpl.rmp_retcode = RMP_E_EOF; + } + retval = 1; + goto sendpkt; + } + + /* + * Set success indication. + */ + rpl->r_rrpl.rmp_retcode = RMP_E_OKAY; + +sendpkt: + /* + * Set up assorted fields in reply packet. + */ + rpl->r_rrpl.rmp_type = RMP_READ_REPL; + COPYWORD(req->r_rrq.rmp_offset, rpl->r_rrpl.rmp_offset); + rpl->r_rrpl.rmp_session = req->r_rrq.rmp_session; + + oldconn->rmplen = RMPREADSIZE(size); /* set size of packet */ + + retval &= SendPacket(oldconn); /* send packet */ + + if (madeconn) /* clean up after ourself */ + FreeConn(oldconn); + + return (retval); +} + +/* +** BootDone -- free up memory allocated for a connection. +** +** Parameters: +** rconn - incoming boot complete packet. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +BootDone(rconn) + RMPCONN *rconn; +{ + RMPCONN *oldconn; + struct rmp_packet *rpl; + + /* + * If we cant find the connection, ignore the request. + */ + if ((oldconn = FindConn(rconn)) == NULL) { + syslog(LOG_ERR, "BootDone: no existing connection (%s)", + EnetStr(rconn)); + return(0); + } + + rpl = &oldconn->rmp; /* cache ptr to RMP packet */ + + /* + * Make sure Session ID's match. + */ + if (rconn->rmp.r_rrq.rmp_session != + ((rpl->r_type == RMP_BOOT_REPL)? rpl->r_brpl.rmp_session: + rpl->r_rrpl.rmp_session)) { + syslog(LOG_ERR, "BootDone: bad session id (%s)", + EnetStr(rconn)); + return(0); + } + + RemoveConn(oldconn); /* remove connection */ + + syslog(LOG_INFO, "%s: boot complete", EnetStr(rconn)); + + return(1); +} + +/* +** SendPacket -- send an RMP packet to a remote host. +** +** Parameters: +** rconn - packet to be sent. +** +** Returns: +** 1 on success, 0 on failure. +** +** Side Effects: +** none. +*/ +int +SendPacket(rconn) + register RMPCONN *rconn; +{ + /* + * Set Ethernet Destination address to Source (BPF and the enet + * driver will take care of getting our source address set). + */ + bcopy((char *)&rconn->rmp.hp_hdr.saddr[0], + (char *)&rconn->rmp.hp_hdr.daddr[0], RMP_ADDRLEN); + rconn->rmp.hp_hdr.len = rconn->rmplen - sizeof(struct hp_hdr); + + /* + * Reverse 802.2/HP Extended Source & Destination Access Pts. + */ + rconn->rmp.hp_llc.dxsap = HPEXT_SXSAP; + rconn->rmp.hp_llc.sxsap = HPEXT_DXSAP; + + /* + * Last time this connection was active. + */ + (void) gettimeofday(&rconn->tstamp, (struct timezone *)0); + + if (DbgFp != NULL) /* display packet */ + DispPkt(rconn,DIR_SENT); + + /* + * Send RMP packet to remote host. + */ + return(BpfWrite(rconn)); +} diff --git a/rbootd.tproj/utils.c b/rbootd.tproj/utils.c new file mode 100644 index 0000000..7837471 --- /dev/null +++ b/rbootd.tproj/utils.c @@ -0,0 +1,580 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1992 The University of Utah and the Center + * for Software Science (CSS). + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * the Center for Software Science of the University of Utah Computer + * Science Department. CSS requests users of this software to return + * to css-dist@cs.utah.edu any improvements that they make and grant + * CSS redistribution rights. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)utils.c 8.2 (Berkeley) 2/22/94 + * + * Utah $Hdr: utils.c 3.1 92/07/06$ + * Author: Jeff Forys, University of Utah CSS + */ + +#ifndef lint +static char sccsid[] = "@(#)utils.c 8.2 (Berkeley) 2/22/94"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "defs.h" + +/* +** DispPkt -- Display the contents of an RMPCONN packet. +** +** Parameters: +** rconn - packet to be displayed. +** direct - direction packet is going (DIR_*). +** +** Returns: +** Nothing. +** +** Side Effects: +** None. +*/ +void +DispPkt(rconn, direct) + RMPCONN *rconn; + int direct; +{ + static char BootFmt[] = "\t\tRetCode:%u SeqNo:%lx SessID:%x Vers:%u"; + static char ReadFmt[] = "\t\tRetCode:%u Offset:%lx SessID:%x\n"; + + struct tm *tmp; + register struct rmp_packet *rmp; + int i, omask; + u_int t; + + /* + * Since we will be working with RmpConns as well as DbgFp, we + * must block signals that can affect either. + */ + omask = sigblock(sigmask(SIGHUP)|sigmask(SIGUSR1)|sigmask(SIGUSR2)); + + if (DbgFp == NULL) { /* sanity */ + (void) sigsetmask(omask); + return; + } + + /* display direction packet is going using '>>>' or '<<<' */ + fputs((direct==DIR_RCVD)?"<<< ":(direct==DIR_SENT)?">>> ":"", DbgFp); + + /* display packet timestamp */ + tmp = localtime((time_t *)&rconn->tstamp.tv_sec); + fprintf(DbgFp, "%02d:%02d:%02d.%06ld ", tmp->tm_hour, tmp->tm_min, + tmp->tm_sec, rconn->tstamp.tv_usec); + + /* display src or dst addr and information about network interface */ + fprintf(DbgFp, "Addr: %s Intf: %s\n", EnetStr(rconn), IntfName); + + rmp = &rconn->rmp; + + /* display IEEE 802.2 Logical Link Control header */ + (void) fprintf(DbgFp, "\t802.2 LLC: DSAP:%x SSAP:%x CTRL:%x\n", + rmp->hp_llc.dsap, rmp->hp_llc.ssap, rmp->hp_llc.cntrl); + + /* display HP extensions to 802.2 Logical Link Control header */ + (void) fprintf(DbgFp, "\tHP Ext: DXSAP:%x SXSAP:%x\n", + rmp->hp_llc.dxsap, rmp->hp_llc.sxsap); + + /* + * Display information about RMP packet using type field to + * determine what kind of packet this is. + */ + switch(rmp->r_type) { + case RMP_BOOT_REQ: /* boot request */ + (void) fprintf(DbgFp, "\tBoot Request:"); + GETWORD(rmp->r_brq.rmp_seqno, t); + if (rmp->r_brq.rmp_session == RMP_PROBESID) { + if (WORDZE(rmp->r_brq.rmp_seqno)) + fputs(" (Send Server ID)", DbgFp); + else + fprintf(DbgFp," (Send Filename #%u)",t); + } + (void) fputc('\n', DbgFp); + (void) fprintf(DbgFp, BootFmt, rmp->r_brq.rmp_retcode, + t, rmp->r_brq.rmp_session, + rmp->r_brq.rmp_version); + (void) fprintf(DbgFp, "\n\t\tMachine Type: "); + for (i = 0; i < RMP_MACHLEN; i++) + (void) fputc(rmp->r_brq.rmp_machtype[i], DbgFp); + DspFlnm(rmp->r_brq.rmp_flnmsize, &rmp->r_brq.rmp_flnm); + break; + case RMP_BOOT_REPL: /* boot reply */ + fprintf(DbgFp, "\tBoot Reply:\n"); + GETWORD(rmp->r_brpl.rmp_seqno, t); + (void) fprintf(DbgFp, BootFmt, rmp->r_brpl.rmp_retcode, + t, rmp->r_brpl.rmp_session, + rmp->r_brpl.rmp_version); + DspFlnm(rmp->r_brpl.rmp_flnmsize,&rmp->r_brpl.rmp_flnm); + break; + case RMP_READ_REQ: /* read request */ + (void) fprintf(DbgFp, "\tRead Request:\n"); + GETWORD(rmp->r_rrq.rmp_offset, t); + (void) fprintf(DbgFp, ReadFmt, rmp->r_rrq.rmp_retcode, + t, rmp->r_rrq.rmp_session); + (void) fprintf(DbgFp, "\t\tNoOfBytes: %u\n", + rmp->r_rrq.rmp_size); + break; + case RMP_READ_REPL: /* read reply */ + (void) fprintf(DbgFp, "\tRead Reply:\n"); + GETWORD(rmp->r_rrpl.rmp_offset, t); + (void) fprintf(DbgFp, ReadFmt, rmp->r_rrpl.rmp_retcode, + t, rmp->r_rrpl.rmp_session); + (void) fprintf(DbgFp, "\t\tNoOfBytesSent: %d\n", + rconn->rmplen - RMPREADSIZE(0)); + break; + case RMP_BOOT_DONE: /* boot complete */ + (void) fprintf(DbgFp, "\tBoot Complete:\n"); + (void) fprintf(DbgFp, "\t\tRetCode:%u SessID:%x\n", + rmp->r_done.rmp_retcode, + rmp->r_done.rmp_session); + break; + default: /* ??? */ + (void) fprintf(DbgFp, "\tUnknown Type:(%d)\n", + rmp->r_type); + } + (void) fputc('\n', DbgFp); + (void) fflush(DbgFp); + + (void) sigsetmask(omask); /* reset old signal mask */ +} + + +/* +** GetEtherAddr -- convert an RMP (Ethernet) address into a string. +** +** An RMP BOOT packet has been received. Look at the type field +** and process Boot Requests, Read Requests, and Boot Complete +** packets. Any other type will be dropped with a warning msg. +** +** Parameters: +** addr - array of RMP_ADDRLEN bytes. +** +** Returns: +** Pointer to static string representation of `addr'. +** +** Side Effects: +** None. +** +** Warnings: +** - The return value points to a static buffer; it must +** be copied if it's to be saved. +** - For speed, we assume a u_char consists of 8 bits. +*/ +char * +GetEtherAddr(addr) + u_char *addr; +{ + static char Hex[] = "0123456789abcdef"; + static char etherstr[RMP_ADDRLEN*3]; + register int i; + register char *cp1, *cp2; + + /* + * For each byte in `addr', convert it to ":". + * The last byte does not get a trailing `:' appended. + */ + i = 0; + cp1 = (char *)addr; + cp2 = etherstr; + for(;;) { + *cp2++ = Hex[*cp1 >> 4 & 0xf]; + *cp2++ = Hex[*cp1++ & 0xf]; + if (++i == RMP_ADDRLEN) + break; + *cp2++ = ':'; + } + *cp2 = '\0'; + + return(etherstr); +} + + +/* +** DispFlnm -- Print a string of bytes to DbgFp (often, a file name). +** +** Parameters: +** size - number of bytes to print. +** flnm - address of first byte. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Characters are sent to `DbgFp'. +*/ +void +DspFlnm(size, flnm) + register u_int size; + register char *flnm; +{ + register int i; + + (void) fprintf(DbgFp, "\n\t\tFile Name (%d): <", size); + for (i = 0; i < size; i++) + (void) fputc(*flnm++, DbgFp); + (void) fputs(">\n", DbgFp); +} + + +/* +** NewClient -- allocate memory for a new CLIENT. +** +** Parameters: +** addr - RMP (Ethernet) address of new client. +** +** Returns: +** Ptr to new CLIENT or NULL if we ran out of memory. +** +** Side Effects: +** - Memory will be malloc'd for the new CLIENT. +** - If malloc() fails, a log message will be generated. +*/ +CLIENT * +NewClient(addr) + u_char *addr; +{ + CLIENT *ctmp; + + if ((ctmp = (CLIENT *) malloc(sizeof(CLIENT))) == NULL) { + syslog(LOG_ERR, "NewClient: out of memory (%s)", + GetEtherAddr(addr)); + return(NULL); + } + + bzero(ctmp, sizeof(CLIENT)); + bcopy(addr, &ctmp->addr[0], RMP_ADDRLEN); + return(ctmp); +} + +/* +** FreeClient -- free linked list of Clients. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - All malloc'd memory associated with the linked list of +** CLIENTS will be free'd; `Clients' will be set to NULL. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +FreeClients() +{ + register CLIENT *ctmp; + + while (Clients != NULL) { + ctmp = Clients; + Clients = Clients->next; + FreeClient(ctmp); + } +} + +/* +** NewStr -- allocate memory for a character array. +** +** Parameters: +** str - null terminated character array. +** +** Returns: +** Ptr to new character array or NULL if we ran out of memory. +** +** Side Effects: +** - Memory will be malloc'd for the new character array. +** - If malloc() fails, a log message will be generated. +*/ +char * +NewStr(str) + char *str; +{ + char *stmp; + + if ((stmp = (char *)malloc((unsigned) (strlen(str)+1))) == NULL) { + syslog(LOG_ERR, "NewStr: out of memory (%s)", str); + return(NULL); + } + + (void) strcpy(stmp, str); + return(stmp); +} + +/* +** To save time, NewConn and FreeConn maintain a cache of one RMPCONN +** in `LastFree' (defined below). +*/ + +static RMPCONN *LastFree = NULL; + +/* +** NewConn -- allocate memory for a new RMPCONN connection. +** +** Parameters: +** rconn - initialization template for new connection. +** +** Returns: +** Ptr to new RMPCONN or NULL if we ran out of memory. +** +** Side Effects: +** - Memory may be malloc'd for the new RMPCONN (if not cached). +** - If malloc() fails, a log message will be generated. +*/ +RMPCONN * +NewConn(rconn) + RMPCONN *rconn; +{ + RMPCONN *rtmp; + + if (LastFree == NULL) { /* nothing cached; make a new one */ + if ((rtmp = (RMPCONN *) malloc(sizeof(RMPCONN))) == NULL) { + syslog(LOG_ERR, "NewConn: out of memory (%s)", + EnetStr(rconn)); + return(NULL); + } + } else { /* use the cached RMPCONN */ + rtmp = LastFree; + LastFree = NULL; + } + + /* + * Copy template into `rtmp', init file descriptor to `-1' and + * set ptr to next elem NULL. + */ + bcopy((char *)rconn, (char *)rtmp, sizeof(RMPCONN)); + rtmp->bootfd = -1; + rtmp->next = NULL; + + return(rtmp); +} + +/* +** FreeConn -- Free memory associated with an RMPCONN connection. +** +** Parameters: +** rtmp - ptr to RMPCONN to be free'd. +** +** Returns: +** Nothing. +** +** Side Effects: +** - Memory associated with `rtmp' may be free'd (or cached). +** - File desc associated with `rtmp->bootfd' will be closed. +*/ +void +FreeConn(rtmp) + register RMPCONN *rtmp; +{ + /* + * If the file descriptor is in use, close the file. + */ + if (rtmp->bootfd >= 0) { + (void) close(rtmp->bootfd); + rtmp->bootfd = -1; + } + + if (LastFree == NULL) /* cache for next time */ + rtmp = LastFree; + else /* already one cached; free this one */ + free((char *)rtmp); +} + +/* +** FreeConns -- free linked list of RMPCONN connections. +** +** Parameters: +** None. +** +** Returns: +** Nothing. +** +** Side Effects: +** - All malloc'd memory associated with the linked list of +** connections will be free'd; `RmpConns' will be set to NULL. +** - If LastFree is != NULL, it too will be free'd & NULL'd. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +FreeConns() +{ + register RMPCONN *rtmp; + + while (RmpConns != NULL) { + rtmp = RmpConns; + RmpConns = RmpConns->next; + FreeConn(rtmp); + } + + if (LastFree != NULL) { + free((char *)LastFree); + LastFree = NULL; + } +} + +/* +** AddConn -- Add a connection to the linked list of connections. +** +** Parameters: +** rconn - connection to be added. +** +** Returns: +** Nothing. +** +** Side Effects: +** - RmpConn will point to new connection. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +AddConn(rconn) + register RMPCONN *rconn; +{ + if (RmpConns != NULL) + rconn->next = RmpConns; + RmpConns = rconn; +} + +/* +** FindConn -- Find a connection in the linked list of connections. +** +** We use the RMP (Ethernet) address as the basis for determining +** if this is the same connection. According to the Remote Maint +** Protocol, we can only have one connection with any machine. +** +** Parameters: +** rconn - connection to be found. +** +** Returns: +** Matching connection from linked list or NULL if not found. +** +** Side Effects: +** None. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +RMPCONN * +FindConn(rconn) + register RMPCONN *rconn; +{ + register RMPCONN *rtmp; + + for (rtmp = RmpConns; rtmp != NULL; rtmp = rtmp->next) + if (bcmp((char *)&rconn->rmp.hp_hdr.saddr[0], + (char *)&rtmp->rmp.hp_hdr.saddr[0], RMP_ADDRLEN) == 0) + break; + + return(rtmp); +} + +/* +** RemoveConn -- Remove a connection from the linked list of connections. +** +** Parameters: +** rconn - connection to be removed. +** +** Returns: +** Nothing. +** +** Side Effects: +** - If found, an RMPCONN will cease to exist and it will +** be removed from the linked list. +** +** Warnings: +** - This routine must be called with SIGHUP blocked. +*/ +void +RemoveConn(rconn) + register RMPCONN *rconn; +{ + register RMPCONN *thisrconn, *lastrconn; + + if (RmpConns == rconn) { /* easy case */ + RmpConns = RmpConns->next; + FreeConn(rconn); + } else { /* must traverse linked list */ + lastrconn = RmpConns; /* set back ptr */ + thisrconn = lastrconn->next; /* set current ptr */ + while (thisrconn != NULL) { + if (rconn == thisrconn) { /* found it */ + lastrconn->next = thisrconn->next; + FreeConn(thisrconn); + break; + } + lastrconn = thisrconn; + thisrconn = thisrconn->next; + } + } +} diff --git a/rcp.tproj/Makefile b/rcp.tproj/Makefile new file mode 100644 index 0000000..a35583a --- /dev/null +++ b/rcp.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rcp + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = extern.h pathnames.h + +CFILES = rcp.c util.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\ + rcp.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /bin +WINDOWS_INSTALLDIR = /bin +PDO_UNIX_INSTALLDIR = /bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rcp.tproj/Makefile.dist b/rcp.tproj/Makefile.dist new file mode 100644 index 0000000..898f9a7 --- /dev/null +++ b/rcp.tproj/Makefile.dist @@ -0,0 +1,13 @@ +# @(#)Makefile 8.1 (Berkeley) 7/19/93 + +PROG= rcp +SRCS= rcp.c krcmd.c kcmd.c util.c +CFLAGS+=-DKERBEROS -DCRYPT +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +BINOWN= root +BINMODE=4555 +INSTALLFLAGS=-fschg +.PATH: ${.CURDIR}/../../usr.bin/rlogin + +.include diff --git a/rcp.tproj/Makefile.postamble b/rcp.tproj/Makefile.postamble new file mode 100644 index 0000000..54c0935 --- /dev/null +++ b/rcp.tproj/Makefile.postamble @@ -0,0 +1,5 @@ +VPATH += :$(SRCROOT)$(SRCPATH)/../rlogin.tproj +INSTALL_PERMISSIONS = 4555 # If set, 'install' chmod's executable to this + +after_install:: + $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME) diff --git a/rcp.tproj/Makefile.preamble b/rcp.tproj/Makefile.preamble new file mode 100644 index 0000000..8f3d6b7 --- /dev/null +++ b/rcp.tproj/Makefile.preamble @@ -0,0 +1,5 @@ +RLOGIN_CFILES = krcmd.c des_rw.c +OTHER_OFILES = $(RLOGIN_CFILES:.c=.o) +VPATH_PREAMBLE = ../rlogin.tproj: +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/rcp.tproj/PB.project b/rcp.tproj/PB.project new file mode 100644 index 0000000..c2b93b6 --- /dev/null +++ b/rcp.tproj/PB.project @@ -0,0 +1,29 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (extern.h, pathnames.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rcp.c, util.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, rcp.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_INSTALLDIR = /bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = rcp; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = rcp; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rcp; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = rcp; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rcp.tproj/extern.h b/rcp.tproj/extern.h new file mode 100644 index 0000000..706251f --- /dev/null +++ b/rcp.tproj/extern.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 5/31/93 + */ + +typedef struct { + int cnt; + char *buf; +} BUF; + +extern int iamremote; + +BUF *allocbuf __P((BUF *, int, int)); +char *colon __P((char *)); +void lostconn __P((int)); +void nospace __P((void)); +int okname __P((char *)); +void run_err __P((const char *, ...)); +int susystem __P((char *, int)); +void verifydir __P((char *)); diff --git a/rcp.tproj/pathnames.h b/rcp.tproj/pathnames.h new file mode 100644 index 0000000..a93c4e6 --- /dev/null +++ b/rcp.tproj/pathnames.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 5/31/93 + */ + +#include + +#define _PATH_CP "/bin/cp" +#define _PATH_RSH "/usr/bin/rsh" diff --git a/rcp.tproj/rcp.1 b/rcp.tproj/rcp.1 new file mode 100644 index 0000000..bff0a01 --- /dev/null +++ b/rcp.tproj/rcp.1 @@ -0,0 +1,159 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rcp.1 8.1 (Berkeley) 5/31/93 +.\" +.Dd May 31, 1993 +.Dt RCP 1 +.Os BSD 4.3r +.Sh NAME +.Nm rcp +.Nd remote file copy +.Sh SYNOPSIS +.Nm rcp +.Op Fl Kpx +.Op Fl k Ar realm +.Ar file1 file2 +.Nm rcp +.Op Fl Kprx +.Op Fl k Ar realm +.Ar file ... +.Ar directory +.Sh DESCRIPTION +.Nm Rcp +copies files between machines. Each +.Ar file +or +.Ar directory +argument is either a remote file name of the +form ``rname@rhost:path'', or a local file name (containing no `:' characters, +or a `/' before any `:'s). +.Pp +.Bl -tag -width flag +.It Fl K +The +.Fl K +option turns off all Kerberos authentication. +.It Fl k +The +.Fl k +option requests +.Nm rcp +to obtain tickets +for the remote host in realm +.Ar realm +instead of the remote host's realm as determined by +.Xr krb_realmofhost 3 . +.It Fl p +The +.Fl p +option causes +.Nm rcp +to attempt to preserve (duplicate) in its copies the modification +times and modes of the source files, ignoring the +.Ar umask . +By default, the mode and owner of +.Ar file2 +are preserved if it already existed; otherwise the mode of the source file +modified by the +.Xr umask 2 +on the destination host is used. +.It Fl r +If any of the source files are directories, +.Nm rcp +copies each subtree rooted at that name; in this case +the destination must be a directory. +.It Fl x +The +.Fl x +option turns on +.Tn DES +encryption for all data passed by +.Nm rcp . +This may impact response time and +.Tn CPU +utilization, but provides +increased security. +.El +.Pp +If +.Ar path +is not a full path name, it is interpreted relative to +the login directory of the specified user +.Ar ruser +on +.Ar rhost , +or your current user name if no other remote user name is specified. +A +.Ar path +on a remote host may be quoted (using \e, ", or \(aa) +so that the metacharacters are interpreted remotely. +.Pp +.Nm Rcp +does not prompt for passwords; it performs remote execution +via +.Xr rsh 1 , +and requires the same authorization. +.Pp +.Nm Rcp +handles third party copies, where neither source nor target files +are on the current machine. +.Sh SEE ALSO +.Xr cp 1 , +.Xr ftp 1 , +.Xr rsh 1 , +.Xr rlogin 1 +.Sh HISTORY +The +.Nm rcp +command appeared in +.Bx 4.2 . +The version of +.Nm rcp +described here +has been reimplemented with Kerberos in +.Bx 4.3 Reno . +.Sh BUGS +Doesn't detect all cases where the target of a copy might +be a file in cases where only a directory should be legal. +.Pp +Is confused by any output generated by commands in a +.Pa \&.login , +.Pa \&.profile , +or +.Pa \&.cshrc +file on the remote host. +.Pp +The destination user and hostname may have to be specified as +``rhost.rname'' when the destination machine is running the +.Bx 4.2 +version of +.Nm rcp . diff --git a/rcp.tproj/rcp.c b/rcp.tproj/rcp.c new file mode 100644 index 0000000..579f328 --- /dev/null +++ b/rcp.tproj/rcp.c @@ -0,0 +1,938 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1990, 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pathnames.h" +#include "extern.h" + +#ifdef KERBEROS +#include +#include + +char dst_realm_buf[REALM_SZ]; +char *dest_realm = NULL; +int use_kerberos = 1; +CREDENTIALS cred; +Key_schedule schedule; +extern char *krb_realmofhost(); +#ifdef CRYPT +int doencrypt = 0; +#define OPTIONS "dfKk:prtx" +#else +#define OPTIONS "dfKk:prt" +#endif +#else +#define OPTIONS "dfprt" +#endif + +struct passwd *pwd; +u_short port; +uid_t userid; +int errs, rem; +int pflag, iamremote, iamrecursive, targetshouldbedirectory; + +#define CMDNEEDS 64 +char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ + +#ifdef KERBEROS +int kerberos __P((char **, char *, char *, char *)); +void oldw __P((const char *, ...)); +#endif +int response __P((void)); +void rsource __P((char *, struct stat *)); +void sink __P((int, char *[])); +void source __P((int, char *[])); +void tolocal __P((int, char *[])); +void toremote __P((char *, int, char *[])); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct servent *sp; + int ch, fflag, tflag; + char *targ, *shell; + + fflag = tflag = 0; + while ((ch = getopt(argc, argv, OPTIONS)) != EOF) + switch(ch) { /* User-visible flags. */ + case 'K': +#ifdef KERBEROS + use_kerberos = 0; +#endif + break; +#ifdef KERBEROS + case 'k': + dest_realm = dst_realm_buf; + (void)strncpy(dst_realm_buf, optarg, REALM_SZ); + break; +#ifdef CRYPT + case 'x': + doencrypt = 1; + /* des_set_key(cred.session, schedule); */ + break; +#endif +#endif + case 'p': + pflag = 1; + break; + case 'r': + iamrecursive = 1; + break; + /* Server options. */ + case 'd': + targetshouldbedirectory = 1; + break; + case 'f': /* "from" */ + iamremote = 1; + fflag = 1; + break; + case 't': /* "to" */ + iamremote = 1; + tflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + +#ifdef KERBEROS + if (use_kerberos) { +#ifdef CRYPT + shell = doencrypt ? "ekshell" : "kshell"; +#else + shell = "kshell"; +#endif + if ((sp = getservbyname(shell, "tcp")) == NULL) { + use_kerberos = 0; + oldw("can't get entry for %s/tcp service", shell); + sp = getservbyname(shell = "shell", "tcp"); + } + } else + sp = getservbyname(shell = "shell", "tcp"); +#else + sp = getservbyname(shell = "shell", "tcp"); +#endif + if (sp == NULL) + errx(1, "%s/tcp: unknown service", shell); + port = sp->s_port; + + if ((pwd = getpwuid(userid = getuid())) == NULL) + errx(1, "unknown user %d", (int)userid); + + rem = STDIN_FILENO; /* XXX */ + + if (fflag) { /* Follow "protocol", send data. */ + (void)response(); + (void)setuid(userid); + source(argc, argv); + exit(errs); + } + + if (tflag) { /* Receive data. */ + (void)setuid(userid); + sink(argc, argv); + exit(errs); + } + + if (argc < 2) + usage(); + if (argc > 2) + targetshouldbedirectory = 1; + + rem = -1; + /* Command to be executed on remote system using "rsh". */ +#ifdef KERBEROS + (void)snprintf(cmd, sizeof(cmd), + "rcp%s%s%s%s", iamrecursive ? " -r" : "", +#ifdef CRYPT + (doencrypt && use_kerberos ? " -x" : ""), +#else + "", +#endif + pflag ? " -p" : "", targetshouldbedirectory ? " -d" : ""); +#else + (void)snprintf(cmd, sizeof(cmd), "rcp%s%s%s", + iamrecursive ? " -r" : "", pflag ? " -p" : "", + targetshouldbedirectory ? " -d" : ""); +#endif + + (void)signal(SIGPIPE, lostconn); + + if (targ = colon(argv[argc - 1])) /* Dest is remote host. */ + toremote(targ, argc, argv); + else { + tolocal(argc, argv); /* Dest is local host. */ + if (targetshouldbedirectory) + verifydir(argv[argc - 1]); + } + exit(errs); +} + +void +toremote(targ, argc, argv) + char *targ, *argv[]; + int argc; +{ + int i, len, tos; + char *bp, *host, *src, *suser, *thost, *tuser; + + *targ++ = 0; + if (*targ == 0) + targ = "."; + + if (thost = strchr(argv[argc - 1], '@')) { + /* user@host */ + *thost++ = 0; + tuser = argv[argc - 1]; + if (*tuser == '\0') + tuser = NULL; + else if (!okname(tuser)) + exit(1); + } else { + thost = argv[argc - 1]; + tuser = NULL; + } + + for (i = 0; i < argc - 1; i++) { + src = colon(argv[i]); + if (src) { /* remote to remote */ + *src++ = 0; + if (*src == 0) + src = "."; + host = strchr(argv[i], '@'); + len = strlen(_PATH_RSH) + strlen(argv[i]) + + strlen(src) + (tuser ? strlen(tuser) : 0) + + strlen(thost) + strlen(targ) + CMDNEEDS + 20; + if (!(bp = malloc(len))) + err(1, NULL); + if (host) { + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') + suser = pwd->pw_name; + else if (!okname(suser)) + continue; + (void)snprintf(bp, len, + "%s %s -l %s -n %s %s '%s%s%s:%s'", + _PATH_RSH, host, suser, cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + } else + (void)snprintf(bp, len, + "exec %s %s -n %s %s '%s%s%s:%s'", + _PATH_RSH, argv[i], cmd, src, + tuser ? tuser : "", tuser ? "@" : "", + thost, targ); + (void)susystem(bp, userid); + (void)free(bp); + } else { /* local to remote */ + if (rem == -1) { + len = strlen(targ) + CMDNEEDS + 20; + if (!(bp = malloc(len))) + err(1, NULL); + (void)snprintf(bp, len, "%s -t %s", cmd, targ); + host = thost; +#ifdef KERBEROS + if (use_kerberos) + rem = kerberos(&host, bp, + pwd->pw_name, + tuser ? tuser : pwd->pw_name); + else +#endif + rem = rcmd(&host, port, pwd->pw_name, + tuser ? tuser : pwd->pw_name, + bp, 0); + if (rem < 0) + exit(1); + tos = IPTOS_THROUGHPUT; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, + &tos, sizeof(int)) < 0) + warn("TOS (ignored)"); + if (response() < 0) + exit(1); + (void)free(bp); + (void)setuid(userid); + } + source(1, argv+i); + } + } +} + +void +tolocal(argc, argv) + int argc; + char *argv[]; +{ + int i, len, tos; + char *bp, *host, *src, *suser; + + for (i = 0; i < argc - 1; i++) { + if (!(src = colon(argv[i]))) { /* Local to local. */ + len = strlen(_PATH_CP) + strlen(argv[i]) + + strlen(argv[argc - 1]) + 20; + if (!(bp = malloc(len))) + err(1, NULL); + (void)snprintf(bp, len, "exec %s%s%s %s %s", _PATH_CP, + iamrecursive ? " -r" : "", pflag ? " -p" : "", + argv[i], argv[argc - 1]); + if (susystem(bp, userid)) + ++errs; + (void)free(bp); + continue; + } + *src++ = 0; + if (*src == 0) + src = "."; + if ((host = strchr(argv[i], '@')) == NULL) { + host = argv[i]; + suser = pwd->pw_name; + } else { + *host++ = 0; + suser = argv[i]; + if (*suser == '\0') + suser = pwd->pw_name; + else if (!okname(suser)) + continue; + } + len = strlen(src) + CMDNEEDS + 20; + if ((bp = malloc(len)) == NULL) + err(1, NULL); + (void)snprintf(bp, len, "%s -f %s", cmd, src); + rem = +#ifdef KERBEROS + use_kerberos ? + kerberos(&host, bp, pwd->pw_name, suser) : +#endif + rcmd(&host, port, pwd->pw_name, suser, bp, 0); + (void)free(bp); + if (rem < 0) { + ++errs; + continue; + } + (void)seteuid(userid); + tos = IPTOS_THROUGHPUT; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) + warn("TOS (ignored)"); + sink(1, argv + argc - 1); + (void)seteuid(0); + (void)close(rem); + rem = -1; + } +} + +void +source(argc, argv) + int argc; + char *argv[]; +{ + struct stat stb; + static BUF buffer; + BUF *bp; + off_t i; + int amt, fd, haderr, indx, result; + char *last, *name, buf[BUFSIZ]; + + for (indx = 0; indx < argc; ++indx) { + name = argv[indx]; + if ((fd = open(name, O_RDONLY, 0)) < 0) + goto syserr; + if (fstat(fd, &stb)) { +syserr: run_err("%s: %s", name, strerror(errno)); + goto next; + } + switch (stb.st_mode & S_IFMT) { + case S_IFREG: + break; + case S_IFDIR: + if (iamrecursive) { + rsource(name, &stb); + goto next; + } + /* FALLTHROUGH */ + default: + run_err("%s: not a regular file", name); + goto next; + } + if ((last = strrchr(name, '/')) == NULL) + last = name; + else + ++last; + if (pflag) { + /* + * Make it compatible with possible future + * versions expecting microseconds. + */ + (void)snprintf(buf, sizeof(buf), "T%ld 0 %ld 0\n", + stb.st_mtimespec.tv_sec, stb.st_atimespec.tv_sec); + (void)write(rem, buf, strlen(buf)); + if (response() < 0) + goto next; + } +#define MODEMASK (S_ISUID|S_ISGID|S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO) + (void)snprintf(buf, sizeof(buf), "C%04o %qd %s\n", + stb.st_mode & MODEMASK, stb.st_size, last); + (void)write(rem, buf, strlen(buf)); + if (response() < 0) + goto next; + if ((bp = allocbuf(&buffer, fd, BUFSIZ)) == NULL) { +next: (void)close(fd); + continue; + } + + /* Keep writing after an error so that we stay sync'd up. */ + for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { + amt = bp->cnt; + if (i + amt > stb.st_size) + amt = stb.st_size - i; + if (!haderr) { + result = read(fd, bp->buf, amt); + if (result != amt) + haderr = result >= 0 ? EIO : errno; + } + if (haderr) + (void)write(rem, bp->buf, amt); + else { + result = write(rem, bp->buf, amt); + if (result != amt) + haderr = result >= 0 ? EIO : errno; + } + } + if (close(fd) && !haderr) + haderr = errno; + if (!haderr) + (void)write(rem, "", 1); + else + run_err("%s: %s", name, strerror(haderr)); + (void)response(); + } +} + +void +rsource(name, statp) + char *name; + struct stat *statp; +{ + DIR *dirp; + struct dirent *dp; + char *last, *vect[1], path[MAXPATHLEN]; + + if (!(dirp = opendir(name))) { + run_err("%s: %s", name, strerror(errno)); + return; + } + last = strrchr(name, '/'); + if (last == 0) + last = name; + else + last++; + if (pflag) { + (void)snprintf(path, sizeof(path), "T%ld 0 %ld 0\n", + statp->st_mtimespec.tv_sec, statp->st_atimespec.tv_sec); + (void)write(rem, path, strlen(path)); + if (response() < 0) { + closedir(dirp); + return; + } + } + (void)snprintf(path, sizeof(path), + "D%04o %d %s\n", statp->st_mode & MODEMASK, 0, last); + (void)write(rem, path, strlen(path)); + if (response() < 0) { + closedir(dirp); + return; + } + while (dp = readdir(dirp)) { + if (dp->d_ino == 0) + continue; + if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) + continue; + if (strlen(name) + 1 + strlen(dp->d_name) >= MAXPATHLEN - 1) { + run_err("%s/%s: name too long", name, dp->d_name); + continue; + } + (void)snprintf(path, sizeof(path), "%s/%s", name, dp->d_name); + vect[0] = path; + source(1, vect); + } + (void)closedir(dirp); + (void)write(rem, "E\n", 2); + (void)response(); +} + +void +sink(argc, argv) + int argc; + char *argv[]; +{ + static BUF buffer; + struct stat stb; + struct timeval tv[2]; + enum { YES, NO, DISPLAYED } wrerr; + BUF *bp; + off_t i, j; + int amt, count, exists, first, mask, mode, ofd, omode; + int setimes, size, targisdir, wrerrno; + char ch, *cp, *np, *targ, *why, *vect[1], buf[BUFSIZ]; + +#define atime tv[0] +#define mtime tv[1] +#define SCREWUP(str) { why = str; goto screwup; } + + setimes = targisdir = 0; + mask = umask(0); + if (!pflag) + (void)umask(mask); + if (argc != 1) { + run_err("ambiguous target"); + exit(1); + } + targ = *argv; + if (targetshouldbedirectory) + verifydir(targ); + (void)write(rem, "", 1); + if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) + targisdir = 1; + for (first = 1;; first = 0) { + cp = buf; + if (read(rem, cp, 1) <= 0) + return; + if (*cp++ == '\n') + SCREWUP("unexpected "); + do { + if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) + SCREWUP("lost connection"); + *cp++ = ch; + } while (cp < &buf[BUFSIZ - 1] && ch != '\n'); + *cp = 0; + + if (buf[0] == '\01' || buf[0] == '\02') { + if (iamremote == 0) + (void)write(STDERR_FILENO, + buf + 1, strlen(buf + 1)); + if (buf[0] == '\02') + exit(1); + ++errs; + continue; + } + if (buf[0] == 'E') { + (void)write(rem, "", 1); + return; + } + + if (ch == '\n') + *--cp = 0; + +#define getnum(t) (t) = 0; while (isdigit(*cp)) (t) = (t) * 10 + (*cp++ - '0'); + cp = buf; + if (*cp == 'T') { + setimes++; + cp++; + getnum(mtime.tv_sec); + if (*cp++ != ' ') + SCREWUP("mtime.sec not delimited"); + getnum(mtime.tv_usec); + if (*cp++ != ' ') + SCREWUP("mtime.usec not delimited"); + getnum(atime.tv_sec); + if (*cp++ != ' ') + SCREWUP("atime.sec not delimited"); + getnum(atime.tv_usec); + if (*cp++ != '\0') + SCREWUP("atime.usec not delimited"); + (void)write(rem, "", 1); + continue; + } + if (*cp != 'C' && *cp != 'D') { + /* + * Check for the case "rcp remote:foo\* local:bar". + * In this case, the line "No match." can be returned + * by the shell before the rcp command on the remote is + * executed so the ^Aerror_message convention isn't + * followed. + */ + if (first) { + run_err("%s", cp); + exit(1); + } + SCREWUP("expected control record"); + } + mode = 0; + for (++cp; cp < buf + 5; cp++) { + if (*cp < '0' || *cp > '7') + SCREWUP("bad mode"); + mode = (mode << 3) | (*cp - '0'); + } + if (*cp++ != ' ') + SCREWUP("mode not delimited"); + + for (size = 0; isdigit(*cp);) + size = size * 10 + (*cp++ - '0'); + if (*cp++ != ' ') + SCREWUP("size not delimited"); + if (targisdir) { + static char *namebuf; + static int cursize; + size_t need; + + need = strlen(targ) + strlen(cp) + 250; + if (need > cursize) { + if (!(namebuf = malloc(need))) + run_err("%s", strerror(errno)); + } + (void)snprintf(namebuf, need, "%s%s%s", targ, + *targ ? "/" : "", cp); + np = namebuf; + } else + np = targ; + exists = stat(np, &stb) == 0; + if (buf[0] == 'D') { + int mod_flag = pflag; + if (exists) { + if (!S_ISDIR(stb.st_mode)) { + errno = ENOTDIR; + goto bad; + } + if (pflag) + (void)chmod(np, mode); + } else { + /* Handle copying from a read-only directory */ + mod_flag = 1; + if (mkdir(np, mode | S_IRWXU) < 0) + goto bad; + } + vect[0] = np; + sink(1, vect); + if (setimes) { + setimes = 0; + if (utimes(np, tv) < 0) + run_err("%s: set times: %s", + np, strerror(errno)); + } + if (mod_flag) + (void)chmod(np, mode); + continue; + } + omode = mode; + mode |= S_IWRITE; + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { +bad: run_err("%s: %s", np, strerror(errno)); + continue; + } + (void)write(rem, "", 1); + if ((bp = allocbuf(&buffer, ofd, BUFSIZ)) == NULL) { + (void)close(ofd); + continue; + } + cp = bp->buf; + wrerr = NO; + for (count = i = 0; i < size; i += BUFSIZ) { + amt = BUFSIZ; + if (i + amt > size) + amt = size - i; + count += amt; + do { + j = read(rem, cp, amt); + if (j <= 0) { + run_err("%s", j ? strerror(errno) : + "dropped connection"); + exit(1); + } + amt -= j; + cp += j; + } while (amt > 0); + if (count == bp->cnt) { + /* Keep reading so we stay sync'd up. */ + if (wrerr == NO) { + j = write(ofd, bp->buf, count); + if (j != count) { + wrerr = YES; + wrerrno = j >= 0 ? EIO : errno; + } + } + count = 0; + cp = bp->buf; + } + } + if (count != 0 && wrerr == NO && + (j = write(ofd, bp->buf, count)) != count) { + wrerr = YES; + wrerrno = j >= 0 ? EIO : errno; + } + if (ftruncate(ofd, size)) { + run_err("%s: truncate: %s", np, strerror(errno)); + wrerr = DISPLAYED; + } + if (pflag) { + if (exists || omode != mode) + if (fchmod(ofd, omode)) + run_err("%s: set mode: %s", + np, strerror(errno)); + } else { + if (!exists && omode != mode) + if (fchmod(ofd, omode & ~mask)) + run_err("%s: set mode: %s", + np, strerror(errno)); + } + (void)close(ofd); + (void)response(); + if (setimes && wrerr == NO) { + setimes = 0; + if (utimes(np, tv) < 0) { + run_err("%s: set times: %s", + np, strerror(errno)); + wrerr = DISPLAYED; + } + } + switch(wrerr) { + case YES: + run_err("%s: %s", np, strerror(wrerrno)); + break; + case NO: + (void)write(rem, "", 1); + break; + case DISPLAYED: + break; + } + } +screwup: + run_err("protocol error: %s", why); + exit(1); +} + +#ifdef KERBEROS +int +kerberos(host, bp, locuser, user) + char **host, *bp, *locuser, *user; +{ + struct servent *sp; + +again: + if (use_kerberos) { + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(*host); + rem = +#ifdef CRYPT + doencrypt ? + krcmd_mutual(host, + port, user, bp, 0, dest_realm, &cred, schedule) : +#endif + krcmd(host, port, user, bp, 0, dest_realm); + + if (rem < 0) { + use_kerberos = 0; + if ((sp = getservbyname("shell", "tcp")) == NULL) + errx(1, "unknown service shell/tcp"); + if (errno == ECONNREFUSED) + oldw("remote host doesn't support Kerberos"); + else if (errno == ENOENT) + oldw("can't provide Kerberos authentication data"); + port = sp->s_port; + goto again; + } + } else { +#ifdef CRYPT + if (doencrypt) + errx(1, + "the -x option requires Kerberos authentication"); +#endif + rem = rcmd(host, port, locuser, user, bp, 0); + } + return (rem); +} +#endif /* KERBEROS */ + +int +response() +{ + char ch, *cp, resp, rbuf[BUFSIZ]; + + if (read(rem, &resp, sizeof(resp)) != sizeof(resp)) + lostconn(0); + + cp = rbuf; + switch(resp) { + case 0: /* ok */ + return (0); + default: + *cp++ = resp; + /* FALLTHROUGH */ + case 1: /* error, followed by error msg */ + case 2: /* fatal error, "" */ + do { + if (read(rem, &ch, sizeof(ch)) != sizeof(ch)) + lostconn(0); + *cp++ = ch; + } while (cp < &rbuf[BUFSIZ] && ch != '\n'); + + if (!iamremote) + (void)write(STDERR_FILENO, rbuf, cp - rbuf); + ++errs; + if (resp == 1) + return (-1); + exit(1); + } + /* NOTREACHED */ +} + +void +usage() +{ +#ifdef KERBEROS +#ifdef CRYPT + (void)fprintf(stderr, "%s\n\t%s\n", + "usage: rcp [-Kpx] [-k realm] f1 f2", + "or: rcp [-Kprx] [-k realm] f1 ... fn directory"); +#else + (void)fprintf(stderr, "%s\n\t%s\n", + "usage: rcp [-Kp] [-k realm] f1 f2", + "or: rcp [-Kpr] [-k realm] f1 ... fn directory"); +#endif +#else + (void)fprintf(stderr, + "usage: rcp [-p] f1 f2; or: rcp [-pr] f1 ... fn directory\n"); +#endif + exit(1); +} + +#if __STDC__ +#include +#else +#include +#endif + +#ifdef KERBEROS +void +#if __STDC__ +oldw(const char *fmt, ...) +#else +oldw(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "rcp: "); + (void)vfprintf(stderr, fmt, ap); + (void)fprintf(stderr, ", using standard rcp\n"); + va_end(ap); +} +#endif + +void +#if __STDC__ +run_err(const char *fmt, ...) +#else +run_err(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + static FILE *fp; + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + + ++errs; + if (fp == NULL && !(fp = fdopen(rem, "w"))) + return; + (void)fprintf(fp, "%c", 0x01); + (void)fprintf(fp, "rcp: "); + (void)vfprintf(fp, fmt, ap); + (void)fprintf(fp, "\n"); + (void)fflush(fp); + + if (!iamremote) + vwarnx(fmt, ap); + + va_end(ap); +} diff --git a/rcp.tproj/util.c b/rcp.tproj/util.c new file mode 100644 index 0000000..7ee6866 --- /dev/null +++ b/rcp.tproj/util.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +char * +colon(cp) + char *cp; +{ + if (*cp == ':') /* Leading colon is part of file name. */ + return (0); + + for (; *cp; ++cp) { + if (*cp == ':') + return (cp); + if (*cp == '/') + return (0); + } + return (0); +} + +void +verifydir(cp) + char *cp; +{ + struct stat stb; + + if (!stat(cp, &stb)) { + if (S_ISDIR(stb.st_mode)) + return; + errno = ENOTDIR; + } + run_err("%s: %s", cp, strerror(errno)); + exit(1); +} + +int +okname(cp0) + char *cp0; +{ + int c; + char *cp; + + cp = cp0; + do { + c = *cp; + if (c & 0200) + goto bad; + if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-') + goto bad; + } while (*++cp); + return (1); + +bad: warnx("%s: invalid user name", cp0); + return (0); +} + +int +susystem(s, userid) + int userid; + char *s; +{ + sig_t istat, qstat; + int status, w; + pid_t pid; + + pid = vfork(); + switch (pid) { + case -1: + return (127); + + case 0: + (void)setuid(userid); + execl(_PATH_BSHELL, "sh", "-c", s, NULL); + _exit(127); + } + istat = signal(SIGINT, SIG_IGN); + qstat = signal(SIGQUIT, SIG_IGN); + if (waitpid(pid, &status, 0) < 0) + status = -1; + (void)signal(SIGINT, istat); + (void)signal(SIGQUIT, qstat); + return (status); +} + +BUF * +allocbuf(bp, fd, blksize) + BUF *bp; + int fd, blksize; +{ + struct stat stb; + size_t size; + + if (fstat(fd, &stb) < 0) { + run_err("fstat: %s", strerror(errno)); + return (0); + } + size = roundup(stb.st_blksize, blksize); + if (size == 0) + size = blksize; + if (bp->cnt >= size) + return (bp); + if ((bp->buf = realloc(bp->buf, size)) == NULL) { + bp->cnt = 0; + run_err("%s", strerror(errno)); + return (0); + } + bp->cnt = size; + return (bp); +} + +void +lostconn(signo) + int signo; +{ + if (!iamremote) + warnx("lost connection"); + exit(1); +} diff --git a/revnetgroup.tproj/Makefile b/revnetgroup.tproj/Makefile new file mode 100644 index 0000000..a494108 --- /dev/null +++ b/revnetgroup.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = revnetgroup + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = hash.h + +CFILES = hash.c parse_netgroup.c revnetgroup.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble revnetgroup.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/revnetgroup.tproj/Makefile.postamble b/revnetgroup.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/revnetgroup.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/revnetgroup.tproj/Makefile.preamble b/revnetgroup.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/revnetgroup.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/revnetgroup.tproj/PB.project b/revnetgroup.tproj/PB.project new file mode 100644 index 0000000..3a8d039 --- /dev/null +++ b/revnetgroup.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (hash.h); + OTHER_LIBS = (); + OTHER_LINKED = (hash.c, parse_netgroup.c, revnetgroup.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, revnetgroup.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = revnetgroup; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/revnetgroup.tproj/hash.c b/revnetgroup.tproj/hash.c new file mode 100644 index 0000000..9aee4bd --- /dev/null +++ b/revnetgroup.tproj/hash.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $ */ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: hash.c,v 1.4 1997/02/22 14:22:01 peter Exp $ + */ + +#include +#include +#include +#include +#include "hash.h" + +#ifndef lint +static const char rcsid[] = "$OpenBSD: hash.c,v 1.1 1997/04/15 22:06:11 maja Exp $"; +#endif + +/* + * This hash function is stolen directly from the + * Berkeley DB package. It already exists inside libc, but + * it's declared static which prevents us from calling it + * from here. + */ +/* + * OZ's original sdbm hash + */ +u_int32_t +hash(keyarg, len) + const void *keyarg; + register size_t len; +{ + register const u_char *key; + register size_t loop; + register u_int32_t h; + +#define HASHC h = *key++ + 65599 * h + + h = 0; + key = keyarg; + if (len > 0) { + loop = (len + 8 - 1) >> 3; + + switch (len & (8 - 1)) { + case 0: + do { + HASHC; + /* FALLTHROUGH */ + case 7: + HASHC; + /* FALLTHROUGH */ + case 6: + HASHC; + /* FALLTHROUGH */ + case 5: + HASHC; + /* FALLTHROUGH */ + case 4: + HASHC; + /* FALLTHROUGH */ + case 3: + HASHC; + /* FALLTHROUGH */ + case 2: + HASHC; + /* FALLTHROUGH */ + case 1: + HASHC; + } while (--loop); + } + } + return (h); +} + +/* + * Generate a hash value for a given key (character string). + * We mask off all but the lower 8 bits since our table array + * can only hold 256 elements. + */ +u_int32_t hashkey(key) + char *key; +{ + + if (key == NULL) + return (-1); + return(hash((void *)key, strlen(key)) & HASH_MASK); +} + +/* Find an entry in the hash table (may be hanging off a linked list). */ +char *lookup(table, key) + struct group_entry *table[]; + char *key; +{ + struct group_entry *cur; + + cur = table[hashkey(key)]; + + while (cur) { + if (!strcmp(cur->key, key)) + return(cur->data); + cur = cur->next; + } + + return(NULL); +} + +/* + * Store an entry in the main netgroup hash table. Here's how this + * works: the table can only be so big when we initialize it (TABLESIZE) + * but the number of netgroups in the /etc/netgroup file could easily be + * much larger than the table. Since our hash values are adjusted to + * never be greater than TABLESIZE too, this means it won't be long before + * we find ourselves with two keys that hash to the same value. + * + * One way to deal with this is to malloc(2) a second table and start + * doing indirection, but this is a pain in the butt and it's not worth + * going to all that trouble for a dinky little program like this. Instead, + * we turn each table entry into a linked list and simply link keys + * with the same hash value together at the same index location within + * the table. + * + * That's a lot of comment for such a small piece of code, isn't it. + */ +void store (table, key, data) + struct group_entry *table[]; + char *key, *data; +{ + struct group_entry *new; + u_int32_t i; + + i = hashkey(key); + + new = (struct group_entry *)malloc(sizeof(struct group_entry)); + new->key = strdup(key); + new->data = strdup(data); + new->next = table[i]; + table[i] = new; + + return; +} + +/* + * Store a group member entry and/or update its grouplist. This is + * a bit more complicated than the previous function since we have to + * maintain not only the hash table of group members, each group member + * structure also has a linked list of groups hung off it. If handed + * a member name that we haven't encountered before, we have to do + * two things: add that member to the table (possibly hanging them + * off the end of a linked list, as above), and add a group name to + * the member's grouplist list. If we're handed a name that already has + * an entry in the table, then we just have to do one thing, which is + * to update its grouplist. + */ +void mstore (table, key, data, domain) + struct member_entry *table[]; + char *key, *data, *domain; +{ + struct member_entry *cur, *new; + struct grouplist *tmp,*p; + u_int32_t i; + + i = hashkey(key); + cur = table[i]; + + tmp = (struct grouplist *)malloc(sizeof(struct grouplist)); + tmp->groupname = strdup(data); + tmp->next = NULL; + + /* Check if all we have to do is insert a new groupname. */ + while (cur) { + if (!strcmp(cur->key, key) && !strcmp(cur->domain,domain)) { + p = cur->groups; + while(p) { + if (!strcmp(p->groupname,data)) + return; + p = p->next; + } + tmp->next = cur->groups; + cur->groups = tmp; + return; + } + cur = cur->next; + } + + /* Didn't find a match -- add the whole mess to the table. */ + new = (struct member_entry *)malloc(sizeof(struct member_entry)); + new->key = strdup(key); + new->domain = strdup(domain); + new->groups = tmp; + new->next = table[i]; + table[i] = new; + + return; +} diff --git a/revnetgroup.tproj/hash.h b/revnetgroup.tproj/hash.h new file mode 100644 index 0000000..822c9e0 --- /dev/null +++ b/revnetgroup.tproj/hash.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: hash.h,v 1.1 1997/04/15 22:06:12 maja Exp $ */ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: hash.h,v 1.5 1997/02/22 14:22:02 peter Exp $ + */ + +/* Groupname entry hung off a member_entry node. */ +struct grouplist { + char *groupname; + struct grouplist *next; +}; + +/* Entry in the cooked member list hash table. */ +struct member_entry { + char *key; + char *domain; + struct grouplist *groups; + struct member_entry *next; +}; + +/* Entry in the raw netgroup table. */ +struct group_entry { + char *key; + char *data; + struct group_entry *next; +}; + +/* Table size (chosen arbitrarily). Not too big, not too small. */ +#define TABLESIZE 256 +#define HASH_MASK 0x000000FF + +#define LINSIZ 1024 * 10 + +extern void store __P(( struct group_entry ** , char *, char * )); +extern void mstore __P(( struct member_entry ** , char *, char *, char * )); +extern char *lookup __P(( struct group_entry **, char * )); +extern void __endnetgrent __P(( void )); +extern void __setnetgrent __P(( char * )); +extern int __getnetgrent __P(( char **, char **, char ** )); diff --git a/revnetgroup.tproj/parse_netgroup.c b/revnetgroup.tproj/parse_netgroup.c new file mode 100644 index 0000000..0d1e07a --- /dev/null +++ b/revnetgroup.tproj/parse_netgroup.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $ */ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: parse_netgroup.c,v 1.5 1997/02/22 14:22:02 peter Exp $ + */ + +/* + * This is a specially hacked-up version of getnetgrent.c used to parse + * data from the stored hash table of netgroup info rather than from a + * file. It's used mainly for the parse_netgroup() function. All the YP + * stuff and file support has been stripped out since it isn't needed. + */ + +#include +#include +#include +#include +#include "hash.h" + +#ifndef lint +static const char rcsid[] = "$OpenBSD: parse_netgroup.c,v 1.2 1997/08/18 03:11:35 millert Exp $"; +#endif + +/* + * Static Variables and functions used by setnetgrent(), getnetgrent() and + * __endnetgrent(). + * There are two linked lists: + * - linelist is just used by setnetgrent() to parse the net group file via. + * parse_netgrp() + * - netgrp is the list of entries for the current netgroup + */ +struct linelist { + struct linelist *l_next; /* Chain ptr. */ + int l_parsed; /* Flag for cycles */ + char *l_groupname; /* Name of netgroup */ + char *l_line; /* Netgroup entrie(s) to be parsed */ +}; + +struct netgrp { + struct netgrp *ng_next; /* Chain ptr */ + char *ng_str[3]; /* Field pointers, see below */ +}; +#define NG_HOST 0 /* Host name */ +#define NG_USER 1 /* User name */ +#define NG_DOM 2 /* and Domain name */ + +static struct linelist *linehead = (struct linelist *)0; +static struct netgrp *nextgrp = (struct netgrp *)0; +static struct { + struct netgrp *gr; + char *grname; +} grouphead = { + (struct netgrp *)0, + (char *)0, +}; +static int parse_netgrp(); +static struct linelist *read_for_group(); +void __setnetgrent(), __endnetgrent(); +int __getnetgrent(); +extern struct group_entry *gtable[]; + +/* + * setnetgrent() + * Parse the netgroup file looking for the netgroup and build the list + * of netgrp structures. Let parse_netgrp() and read_for_group() do + * most of the work. + */ +void +__setnetgrent(group) + char *group; +{ + /* Sanity check */ + + if (group == NULL || !strlen(group)) + return; + + if (grouphead.gr == (struct netgrp *)0 || + strcmp(group, grouphead.grname)) { + __endnetgrent(); + if (parse_netgrp(group)) + __endnetgrent(); + else { + grouphead.grname = (char *) + malloc(strlen(group) + 1); + strcpy(grouphead.grname, group); + } + } + nextgrp = grouphead.gr; +} + +/* + * Get the next netgroup off the list. + */ +int +__getnetgrent(hostp, userp, domp) + char **hostp, **userp, **domp; +{ + if (nextgrp) { + *hostp = nextgrp->ng_str[NG_HOST]; + *userp = nextgrp->ng_str[NG_USER]; + *domp = nextgrp->ng_str[NG_DOM]; + nextgrp = nextgrp->ng_next; + return (1); + } + return (0); +} + +/* + * __endnetgrent() - cleanup + */ +void +__endnetgrent() +{ + register struct linelist *lp, *olp; + register struct netgrp *gp, *ogp; + + lp = linehead; + while (lp) { + olp = lp; + lp = lp->l_next; + free(olp->l_groupname); + free(olp->l_line); + free((char *)olp); + } + linehead = (struct linelist *)0; + if (grouphead.grname) { + free(grouphead.grname); + grouphead.grname = (char *)0; + } + gp = grouphead.gr; + while (gp) { + ogp = gp; + gp = gp->ng_next; + if (ogp->ng_str[NG_HOST]) + free(ogp->ng_str[NG_HOST]); + if (ogp->ng_str[NG_USER]) + free(ogp->ng_str[NG_USER]); + if (ogp->ng_str[NG_DOM]) + free(ogp->ng_str[NG_DOM]); + free((char *)ogp); + } + grouphead.gr = (struct netgrp *)0; +} + +/* + * Parse the netgroup file setting up the linked lists. + */ +static int +parse_netgrp(group) + char *group; +{ + register char *spos, *epos; + register int len, strpos; +#ifdef DEBUG + register int fields; +#endif + char *pos, *gpos; + struct netgrp *grp; + struct linelist *lp = linehead; + + /* + * First, see if the line has already been read in. + */ + while (lp) { + if (!strcmp(group, lp->l_groupname)) + break; + lp = lp->l_next; + } + if (lp == (struct linelist *)0 && + (lp = read_for_group(group)) == (struct linelist *)0) + return (1); + if (lp->l_parsed) { +#ifdef DEBUG + /* + * This error message is largely superflous since the + * code handles the error condition sucessfully, and + * spewing it out from inside libc can actually hose + * certain programs. + */ + fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname); +#endif + return (1); + } else + lp->l_parsed = 1; + pos = lp->l_line; + /* Watch for null pointer dereferences, dammit! */ + while (pos != NULL && *pos != '\0') { + if (*pos == '(') { + grp = (struct netgrp *)malloc(sizeof (struct netgrp)); + bzero((char *)grp, sizeof (struct netgrp)); + grp->ng_next = grouphead.gr; + grouphead.gr = grp; + pos++; + gpos = strsep(&pos, ")"); +#ifdef DEBUG + fields = 0; +#endif + for (strpos = 0; strpos < 3; strpos++) { + if ((spos = strsep(&gpos, ","))) { +#ifdef DEBUG + fields++; +#endif + while (*spos == ' ' || *spos == '\t') + spos++; + if ((epos = strpbrk(spos, " \t"))) { + *epos = '\0'; + len = epos - spos; + } else + len = strlen(spos); + if (len > 0) { + grp->ng_str[strpos] = (char *) + malloc(len + 1); + bcopy(spos, grp->ng_str[strpos], + len + 1); + } + } else { + /* + * All other systems I've tested + * return NULL for empty netgroup + * fields. It's up to user programs + * to handle the NULLs appropriately. + */ + grp->ng_str[strpos] = NULL; + } + } +#ifdef DEBUG + /* + * Note: on other platforms, malformed netgroup + * entries are not normally flagged. While we + * can catch bad entries and report them, we should + * stay silent by default for compatibility's sake. + */ + if (fields < 3) + fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n", + grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST], + grp->ng_str[NG_USER] == NULL ? "" : ",", + grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER], + grp->ng_str[NG_DOM] == NULL ? "" : ",", + grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM], + lp->l_groupname); +#endif + } else { + spos = strsep(&pos, ", \t"); + if (parse_netgrp(spos)) + continue; + } + /* Watch for null pointer dereferences, dammit! */ + if (pos != NULL) + while (*pos == ' ' || *pos == ',' || *pos == '\t') + pos++; + } + return (0); +} + +/* + * Read the netgroup file and save lines until the line for the netgroup + * is found. Return 1 if eof is encountered. + */ +static struct linelist * +read_for_group(group) + char *group; +{ + register char *pos, *spos, *linep = NULL, *olinep = NULL; + register int len, olen; + int cont; + struct linelist *lp; + char line[LINSIZ + 1]; + char *data = NULL; + + data = lookup (gtable, group); + sprintf(line, "%s %s", group, data); + pos = (char *)&line; +#ifdef CANT_HAPPEN + if (*pos == '#') + continue; +#endif + while (*pos == ' ' || *pos == '\t') + pos++; + spos = pos; + while (*pos != ' ' && *pos != '\t' && *pos != '\n' && + *pos != '\0') + pos++; + len = pos - spos; + while (*pos == ' ' || *pos == '\t') + pos++; + if (*pos != '\n' && *pos != '\0') { + lp = (struct linelist *)malloc(sizeof (*lp)); + lp->l_parsed = 0; + lp->l_groupname = (char *)malloc(len + 1); + bcopy(spos, lp->l_groupname, len); + *(lp->l_groupname + len) = '\0'; + len = strlen(pos); + olen = 0; + /* + * Loop around handling line continuations. + */ + do { + if (*(pos + len - 1) == '\n') + len--; + if (*(pos + len - 1) == '\\') { + len--; + cont = 1; + } else + cont = 0; + if (len > 0) { + linep = (char *)malloc(olen + len + 1); + if (olen > 0) { + bcopy(olinep, linep, olen); + free(olinep); + } + bcopy(pos, linep + olen, len); + olen += len; + *(linep + olen) = '\0'; + olinep = linep; + } +#ifdef CANT_HAPPEN + if (cont) { + if (fgets(line, LINSIZ, netf)) { + pos = line; + len = strlen(pos); + } else + cont = 0; + } +#endif + } while (cont); + lp->l_line = linep; + lp->l_next = linehead; + linehead = lp; +#ifdef CANT_HAPPEN + /* + * If this is the one we wanted, we are done. + */ + if (!strcmp(lp->l_groupname, group)) +#endif + return (lp); + } + return ((struct linelist *)0); +} diff --git a/revnetgroup.tproj/revnetgroup.8 b/revnetgroup.tproj/revnetgroup.8 new file mode 100644 index 0000000..aea4095 --- /dev/null +++ b/revnetgroup.tproj/revnetgroup.8 @@ -0,0 +1,138 @@ +.\" $OpenBSD: revnetgroup.8,v 1.1 1997/04/15 22:06:14 maja Exp $ +.\" Copyright (c) 1995 +.\" Bill Paul . All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Bill Paul. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD: revnetgroup.8,v 1.4 1997/02/22 14:22:03 peter Exp $ +.\" +.Dd October 24, 1995 +.Dt REVNETGROUP 8 +.Os +.Sh NAME +.Nm revnetgroup +.Nd "generate reverse netgroup data" +.Sh SYNOPSIS +.Nm revnetgroup +.Fl u +.Fl h +.Op Fl f Ar netgroup_file +.Sh DESCRIPTION +.Nm revnetgroup +processes the contents of a file in +.Xr netgroup 5 +format into what is called +.Pa reverse netgroup +form. That is, where the original file shows +netgroup memberships in terms of which members reside in a particular +group, the reverse netgroup format specifies what groups are associated +with a particular member. This information is used to generate the +.Nm netgroup.byuser +and +.Nm netgroup.byhosts +YP maps. These reverse netgroup maps are used to help speed up +netgroup lookups, particularly for the +.Fn innetgr +library function. +.Pp +For example, the standard +.Nm /etc/netgroup +file may list a netgroup and a list of its members. Here, the +netgroup is considered the +.Pa key +and the member names are the +.Pa data . +By contrast, the reverse +.Nm netgroup.byusers +database lists each unique +member as the key and the netgroups to which the members belong become +the data. Seperate databases are created to hold information pertaining +to users and hosts; this allows netgroup username lookups +and netgroup hostname lookups to be performed using independent keyspaces. +.Pp +By constructing these reverse netgroup databases (and the corresponding +YP maps) in advance, the +.Xr getnetgrent 3 +library functions are spared from having to work out the dependencies +themselves on the fly. This is important on networks with large numbers +of users and hosts, since it can take a considerable amount of time +to process very large netgroup databases. +.Pp +The +.Nm revnetgroup +command prints its results on the standard output. It is usually called +only by +.Nm /var/yp/\/Makefile +when rebuilding the YP netgroup maps. +.Pp +.Sh OPTIONS +The +.Nm revnetgroup +command supports the following options: +.Bl -tag -width flag +.It Fl u +Generate netgroup.byuser output; only username information in the +original netgroup file is processed. +.It Fl h +Generate netgroup.byhost output; only hostname information in the +original netgroup file is processed. (Note at least one of the +.Fl u +or +.Fl h +flags must be specified.) +.It Op Fl f Ar netgroup_file +The +.Nm revnetgroup +command uses +.Nm /etc/netgroup +as its default input file. The +.Fl f +flag allows the user to specify an alternate input file. Specifying ``-'' +as the input file causes +.Nm revnetgroup +to read from the standard input. +.El +.Sh FILES +.Bl -tag -width Pa -compact +.It Pa /var/yp/\Makefile +The Makefile that calls +.Nm makedbm +and +.Nm revnetgroup +to build the YP databases. +.It Pa /etc/netgroup +The default netgroup database file. This file is most often found +only on the YP master server. +.El +.Sh SEE ALSO +.Xr getnetgrent 3 , +.Xr yp 8 , +.Xr netgroup 5 , +.Xr makedbm 8 +.Sh AUTHOR +Bill Paul diff --git a/revnetgroup.tproj/revnetgroup.c b/revnetgroup.tproj/revnetgroup.c new file mode 100644 index 0000000..a45db99 --- /dev/null +++ b/revnetgroup.tproj/revnetgroup.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: revnetgroup.c,v 1.1 1997/04/15 22:06:15 maja Exp $ */ +/* + * Copyright (c) 1995 + * Bill Paul . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * reverse netgroup map generator program + * + * Written by Bill Paul + * Center for Telecommunications Research + * Columbia University, New York City + * + * $FreeBSD: revnetgroup.c,v 1.7 1997/03/28 15:48:15 imp Exp $ + */ + +#include +#include +#include +#include +#include +#include "hash.h" + +#ifndef lint +static const char rcsid[] = "$OpenBSD: revnetgroup.c,v 1.1 1997/04/15 22:06:15 maja Exp $"; +#endif + +/* Default location of netgroup file. */ +char *netgroup = "/etc/netgroup"; + +/* Stored hash table version of 'forward' netgroup database. */ +struct group_entry *gtable[TABLESIZE]; + +/* + * Stored hash table of 'reverse' netgroup member database + * which we will construct. + */ +struct member_entry *mtable[TABLESIZE]; + +void usage(prog) +char *prog; +{ + fprintf (stderr,"usage: %s -u|-h [-f netgroup file]\n",prog); + exit(1); +} + +extern char *optarg; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + FILE *fp; + char readbuf[LINSIZ]; + struct group_entry *gcur; + struct member_entry *mcur; + char *host, *user, *domain; + int ch; + char *key = NULL, *data = NULL; + int hosts = -1, i; + + if (argc < 2) + usage(argv[0]); + + while ((ch = getopt(argc, argv, "uhf:")) != -1) { + switch(ch) { + case 'u': + if (hosts != -1) { + warnx("please use only one of -u or -h"); + usage(argv[0]); + } + hosts = 0; + break; + case 'h': + if (hosts != -1) { + warnx("please use only one of -u or -h"); + usage(argv[0]); + } + hosts = 1; + break; + case 'f': + netgroup = optarg; + break; + default: + usage(argv[0]); + break; + } + } + + if (hosts == -1) + usage(argv[0]); + + if (strcmp(netgroup, "-")) { + if ((fp = fopen(netgroup, "r")) == NULL) { + err(1,netgroup); + } + } else { + fp = stdin; + } + + /* Stuff all the netgroup names and members into a hash table. */ + while (fgets(readbuf, LINSIZ, fp)) { + if (readbuf[0] == '#') + continue; + /* handle backslash line continuations */ + while(readbuf[strlen(readbuf) - 2] == '\\') { + fgets((char *)&readbuf[strlen(readbuf) - 2], + sizeof(readbuf) - strlen(readbuf), fp); + } + data = NULL; + if ((data = (char *)(strpbrk(readbuf, " \t") + 1)) < (char *)2) + continue; + key = (char *)&readbuf; + *(data - 1) = '\0'; + store(gtable, key, data); + } + + fclose(fp); + + /* + * Find all members of each netgroup and keep track of which + * group they belong to. + */ + for (i = 0; i < TABLESIZE; i++) { + gcur = gtable[i]; + while(gcur) { + __setnetgrent(gcur->key); + while(__getnetgrent(&host, &user, &domain) != NULL) { + if (hosts) { + if (!(host && !strcmp(host,"-"))) { + mstore(mtable, + host ? host : "*", + gcur->key, + domain ? domain : "*"); + } + } else { + if (!(user && !strcmp(user,"-"))) { + mstore(mtable, + user ? user : "*", + gcur->key, + domain ? domain : "*"); + } + } + } + gcur = gcur->next; + } + } + + /* Release resources used by the netgroup parser code. */ + __endnetgrent(); + + /* Spew out the results. */ + for (i = 0; i < TABLESIZE; i++) { + mcur = mtable[i]; + while(mcur) { + struct grouplist *tmp; + printf ("%s.%s\t", mcur->key, mcur->domain); + tmp = mcur->groups; + while(tmp) { + printf ("%s", tmp->groupname); + tmp = tmp->next; + if (tmp) + printf(","); + } + mcur = mcur->next; + printf ("\n"); + } + } + + /* Let the OS free all our resources. */ + exit(0); +} diff --git a/rexecd.tproj/Makefile b/rexecd.tproj/Makefile new file mode 100644 index 0000000..2b445ca --- /dev/null +++ b/rexecd.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rexecd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = rexecd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rexecd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rexecd.tproj/Makefile.postamble b/rexecd.tproj/Makefile.postamble new file mode 100644 index 0000000..7ede358 --- /dev/null +++ b/rexecd.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/rexecd.tproj/Makefile.preamble b/rexecd.tproj/Makefile.preamble new file mode 100644 index 0000000..dcbd1c8 --- /dev/null +++ b/rexecd.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +-include ../Makefile.include diff --git a/rexecd.tproj/PB.project b/rexecd.tproj/PB.project new file mode 100644 index 0000000..aa703bb --- /dev/null +++ b/rexecd.tproj/PB.project @@ -0,0 +1,42 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rexecd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rexecd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rexecd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rexecd.tproj/rexecd.8 b/rexecd.tproj/rexecd.8 new file mode 100644 index 0000000..3035900 --- /dev/null +++ b/rexecd.tproj/rexecd.8 @@ -0,0 +1,149 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rexecd.8 8.3 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt REXECD 8 +.Os BSD 4.2 +.Sh NAME +.Nm rexecd +.Nd remote execution server +.Sh SYNOPSIS +.Nm rexecd +.Sh DESCRIPTION +.Nm Rexecd +is the server for the +.Xr rexec 3 +routine. The server provides remote execution facilities +with authentication based on user names and +passwords. +.Pp +.Nm Rexecd +listens for service requests at the port indicated in +the ``exec'' service specification; see +.Xr services 5 . +When a service request is received the following protocol +is initiated: +.Bl -enum +.It +The server reads characters from the socket up +to a NUL +.Pq Ql \e0 +byte. The resultant string is +interpreted as an +.Tn ASCII +number, base 10. +.It +If the number received in step 1 is non-zero, +it is interpreted as the port number of a secondary +stream to be used for the +.Em stderr . +A second connection is then created to the specified +port on the client's machine. +.It +A NUL terminated user name of at most 16 characters +is retrieved on the initial socket. +.It +A NUL terminated, unencrypted password of at most +16 characters is retrieved on the initial socket. +.It +A NUL terminated command to be passed to a +shell is retrieved on the initial socket. The length of +the command is limited by the upper bound on the size of +the system's argument list. +.It +.Nm Rexecd +then validates the user as is done at login time +and, if the authentication was successful, changes +to the user's home directory, and establishes the user +and group protections of the user. +If any of these steps fail the connection is +aborted with a diagnostic message returned. +.It +A NUL byte is returned on the initial socket +and the command line is passed to the normal login +shell of the user. The +shell inherits the network connections established +by +.Nm rexecd . +.El +.Sh DIAGNOSTICS +Except for the last one listed below, +all diagnostic messages are returned on the initial socket, +after which any network connections are closed. +An error is indicated by a leading byte with a value of +1 (0 is returned in step 7 above upon successful completion +of all the steps prior to the command execution). +.Pp +.Bl -tag -width Ds +.It Sy username too long +The name is +longer than 16 characters. +.It Sy password too long +The password is longer than 16 characters. +.It Sy command too long +The command line passed exceeds the size of the argument +list (as configured into the system). +.It Sy Login incorrect. +No password file entry for the user name existed. +.It Sy Password incorrect. +The wrong password was supplied. +.ne 1i +.It Sy \&No remote directory. +The +.Xr chdir +command to the home directory failed. +.It Sy Try again. +A +.Xr fork +by the server failed. +.It Sy : ... +The user's login shell could not be started. +This message is returned +on the connection associated with the +.Em stderr , +and is not preceded by a flag byte. +.El +.Sh SEE ALSO +.Xr rexec 3 +.Sh BUGS +Indicating ``Login incorrect'' as opposed to ``Password incorrect'' +is a security breach which allows people to probe a system for users +with null passwords. +.Pp +A facility to allow all data and password exchanges to be encrypted should be +present. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/rexecd.tproj/rexecd.c b/rexecd.tproj/rexecd.c new file mode 100644 index 0000000..ec9e009 --- /dev/null +++ b/rexecd.tproj/rexecd.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rexecd.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*VARARGS1*/ +int error(); + +/* + * remote execute server: + * username\0 + * password\0 + * command\0 + * data + */ +/*ARGSUSED*/ +main(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in from; + int fromlen; + + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + (void)fprintf(stderr, + "rexecd: getpeername: %s\n", strerror(errno)); + exit(1); + } + doit(0, &from); +} + +char username[20] = "USER="; +char homedir[64] = "HOME="; +char shell[64] = "SHELL="; +char path[sizeof(_PATH_DEFPATH) + sizeof("PATH=")] = "PATH="; +char *envinit[] = + {homedir, shell, path, username, 0}; +#ifdef __APPLE__ +extern +#endif +char **environ; + +struct sockaddr_in asin = { AF_INET }; + +doit(f, fromp) + int f; + struct sockaddr_in *fromp; +{ + char cmdbuf[NCARGS+1], *cp, *namep; + char user[16], pass[16]; + struct passwd *pwd; + int s; + u_short port; + int pv[2], pid, ready, readfrom, cc; + char buf[BUFSIZ], sig; + int one = 1; + + (void) signal(SIGINT, SIG_DFL); + (void) signal(SIGQUIT, SIG_DFL); + (void) signal(SIGTERM, SIG_DFL); +#ifdef DEBUG + { int t = open(_PATH_TTY, 2); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + (void) close(t); + } + } +#endif + dup2(f, 0); + dup2(f, 1); + dup2(f, 2); + (void) alarm(60); + port = 0; + for (;;) { + char c; + if (read(f, &c, 1) != 1) + exit(1); + if (c == 0) + break; + port = port * 10 + c - '0'; + } + (void) alarm(0); + if (port != 0) { + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + exit(1); + if (bind(s, (struct sockaddr *)&asin, sizeof (asin)) < 0) + exit(1); + (void) alarm(60); + fromp->sin_port = htons(port); + if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) + exit(1); + (void) alarm(0); + } + getstr(user, sizeof(user), "username"); + getstr(pass, sizeof(pass), "password"); + getstr(cmdbuf, sizeof(cmdbuf), "command"); + setpwent(); + pwd = getpwnam(user); + if (pwd == NULL) { + error("Login incorrect.\n"); + exit(1); + } + endpwent(); + if (*pwd->pw_passwd != '\0') { + namep = crypt(pass, pwd->pw_passwd); + if (strcmp(namep, pwd->pw_passwd)) { + error("Password incorrect.\n"); + exit(1); + } + } + if (chdir(pwd->pw_dir) < 0) { + error("No remote directory.\n"); + exit(1); + } + (void) write(2, "\0", 1); + if (port) { + (void) pipe(pv); + pid = fork(); + if (pid == -1) { + error("Try again.\n"); + exit(1); + } + if (pid) { + (void) close(0); (void) close(1); (void) close(2); + (void) close(f); (void) close(pv[1]); + readfrom = (1<pw_shell == '\0') + pwd->pw_shell = _PATH_BSHELL; + if (f > 2) + (void) close(f); + (void) setgid((gid_t)pwd->pw_gid); + initgroups(pwd->pw_name, pwd->pw_gid); + (void) setuid((uid_t)pwd->pw_uid); + (void)strcat(path, _PATH_DEFPATH); + environ = envinit; + strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); + strncat(shell, pwd->pw_shell, sizeof(shell)-7); + strncat(username, pwd->pw_name, sizeof(username)-6); + cp = strrchr(pwd->pw_shell, '/'); + if (cp) + cp++; + else + cp = pwd->pw_shell; + execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); + perror(pwd->pw_shell); + exit(1); +} + +/*VARARGS1*/ +error(fmt, a1, a2, a3) + char *fmt; + int a1, a2, a3; +{ + char buf[BUFSIZ]; + + buf[0] = 1; + (void) sprintf(buf+1, fmt, a1, a2, a3); + (void) write(2, buf, strlen(buf)); +} + +getstr(buf, cnt, err) + char *buf; + int cnt; + char *err; +{ + char c; + + do { + if (read(0, &c, 1) != 1) + exit(1); + *buf++ = c; + if (--cnt == 0) { + error("%s too long\n", err); + exit(1); + } + } while (c != 0); +} diff --git a/rlogin.tproj/Makefile b/rlogin.tproj/Makefile new file mode 100644 index 0000000..bd0c481 --- /dev/null +++ b/rlogin.tproj/Makefile @@ -0,0 +1,55 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rlogin + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = krb.h + +CFILES = des_rw.c kcmd.c krcmd.c rlogin.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rlogin.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DCRYPT +WINDOWS_PB_CFLAGS = -DCRYPT +PDO_UNIX_PB_CFLAGS = -DCRYPT + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rlogin.tproj/Makefile.postamble b/rlogin.tproj/Makefile.postamble new file mode 100644 index 0000000..acddb30 --- /dev/null +++ b/rlogin.tproj/Makefile.postamble @@ -0,0 +1 @@ +INSTALL_PERMISSIONS = 4755 # If set, 'install' chmod's executable to this diff --git a/rlogin.tproj/Makefile.preamble b/rlogin.tproj/Makefile.preamble new file mode 100644 index 0000000..925a5c7 --- /dev/null +++ b/rlogin.tproj/Makefile.preamble @@ -0,0 +1,3 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/rlogin.tproj/PB.project b/rlogin.tproj/PB.project new file mode 100644 index 0000000..2898a5d --- /dev/null +++ b/rlogin.tproj/PB.project @@ -0,0 +1,42 @@ +{ + FILESTABLE = { + CLASSES = (); + C_FILES = (); + H_FILES = (krb.h); + OTHER_LIBS = (); + OTHER_LINKED = (des_rw.c, kcmd.c, krcmd.c, rlogin.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rlogin.1); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DCRYPT"; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = rlogin; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = "-DCRYPT"; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_MAINNIB = rlogin; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rlogin; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = "-DCRYPT"; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_MAINNIB = rlogin; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rlogin.tproj/des_rw.c b/rlogin.tproj/des_rw.c new file mode 100644 index 0000000..4e056cf --- /dev/null +++ b/rlogin.tproj/des_rw.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)des_rw.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef CRYPT +#ifdef KERBEROS +#include + +#include +#include + +#include +#include +#include +#include + +static unsigned char des_inbuf[10240], storage[10240], *store_ptr; +static bit_64 *key; +static u_char *key_schedule; + +/* XXX these should be in a kerberos include file */ +int krb_net_read __P((int, char *, int)); +#ifdef notdef +/* XXX too hard to make this work */ +int des_pcbc_encrypt __P((des_cblock *, des_cblock *, long, + des_key_schedule, des_cblock *, int)); +#endif + +/* + * NB: These routines will not function properly if NBIO + * is set + */ + +/* + * des_set_key + * + * Set des encryption/decryption key for use by the des_read and + * des_write routines + * + * The inkey parameter is actually the DES initial vector, + * and the insched is the DES Key unwrapped for faster decryption + */ + +void +des_set_key(inkey, insched) + bit_64 *inkey; + u_char *insched; +{ + key = inkey; + key_schedule = insched; +} + +void +des_clear_key() +{ + bzero((char *) key, sizeof(C_Block)); + bzero((char *) key_schedule, sizeof(Key_schedule)); +} + + +int +des_read(fd, buf, len) + int fd; + register char *buf; + int len; +{ + int nreturned = 0; + long net_len, rd_len; + int nstored = 0; + + if (nstored >= len) { + (void) bcopy(store_ptr, buf, len); + store_ptr += len; + nstored -= len; + return(len); + } else if (nstored) { + (void) bcopy(store_ptr, buf, nstored); + nreturned += nstored; + buf += nstored; + len -= nstored; + nstored = 0; + } + + if (krb_net_read(fd, (char *)&net_len, sizeof(net_len)) != + sizeof(net_len)) { + /* XXX can't read enough, pipe + must have closed */ + return(0); + } + net_len = ntohl(net_len); + if (net_len <= 0 || net_len > sizeof(des_inbuf)) { + /* preposterous length; assume out-of-sync; only + recourse is to close connection, so return 0 */ + return(0); + } + /* the writer tells us how much real data we are getting, but + we need to read the pad bytes (8-byte boundary) */ + rd_len = roundup(net_len, 8); + if (krb_net_read(fd, (char *)des_inbuf, rd_len) != rd_len) { + /* pipe must have closed, return 0 */ + return(0); + } + (void) des_pcbc_encrypt(des_inbuf, /* inbuf */ + storage, /* outbuf */ + net_len, /* length */ + key_schedule, /* DES key */ + key, /* IV */ + DECRYPT); /* direction */ + + if(net_len < 8) + store_ptr = storage + 8 - net_len; + else + store_ptr = storage; + + nstored = net_len; + if (nstored > len) { + (void) bcopy(store_ptr, buf, len); + nreturned += len; + store_ptr += len; + nstored -= len; + } else { + (void) bcopy(store_ptr, buf, nstored); + nreturned += nstored; + nstored = 0; + } + + return(nreturned); +} + +static unsigned char des_outbuf[10240]; /* > longest write */ + +int +des_write(fd, buf, len) + int fd; + char *buf; + int len; +{ + static int seeded = 0; + static char garbage_buf[8]; + long net_len, garbage; + + if(len < 8) { + if(!seeded) { + seeded = 1; + srandom((int) time((long *)0)); + } + garbage = random(); + /* insert random garbage */ + (void) bcopy(&garbage, garbage_buf, MIN(sizeof(long),8)); + /* this "right-justifies" the data in the buffer */ + (void) bcopy(buf, garbage_buf + 8 - len, len); + } + /* pcbc_encrypt outputs in 8-byte (64 bit) increments */ + + (void) des_pcbc_encrypt((len < 8) ? garbage_buf : buf, + des_outbuf, + (len < 8) ? 8 : len, + key_schedule, /* DES key */ + key, /* IV */ + ENCRYPT); + + /* tell the other end the real amount, but send an 8-byte padded + packet */ + net_len = htonl(len); + (void) write(fd, &net_len, sizeof(net_len)); + (void) write(fd, des_outbuf, roundup(len,8)); + return(len); +} +#endif /* KERBEROS */ +#endif /* CRYPT */ diff --git a/rlogin.tproj/kcmd.c b/rlogin.tproj/kcmd.c new file mode 100644 index 0000000..1482dda --- /dev/null +++ b/rlogin.tproj/kcmd.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if !defined(__APPLE__) || defined(KERBEROS) + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "krb.h" + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#define START_PORT 5120 /* arbitrary */ + +int getport __P((int *)); + +int +kcmd(sock, ahost, rport, locuser, remuser, cmd, fd2p, ticket, service, realm, + cred, schedule, msg_data, laddr, faddr, authopts) + int *sock; + char **ahost; + u_short rport; + char *locuser, *remuser, *cmd; + int *fd2p; + KTEXT ticket; + char *service; + char *realm; + CREDENTIALS *cred; + Key_schedule schedule; + MSG_DAT *msg_data; + struct sockaddr_in *laddr, *faddr; + long authopts; +{ + int s, timo = 1, pid; + long oldmask; + struct sockaddr_in sin, from; + char c; +#ifdef ATHENA_COMPAT + int lport = IPPORT_RESERVED - 1; +#else + int lport = START_PORT; +#endif + struct hostent *hp; + int rc; + char *host_save; + int status; + + pid = getpid(); + hp = gethostbyname(*ahost); + if (hp == NULL) { + /* fprintf(stderr, "%s: unknown host\n", *ahost); */ + return (-1); + } + + host_save = malloc(strlen(hp->h_name) + 1); + strcpy(host_save, hp->h_name); + *ahost = host_save; + +#ifdef KERBEROS + /* If realm is null, look up from table */ + if (realm == NULL || realm[0] == '\0') + realm = krb_realmofhost(host_save); +#endif /* KERBEROS */ + + oldmask = sigblock(sigmask(SIGURG)); + for (;;) { + s = getport(&lport); + if (s < 0) { + if (errno == EAGAIN) + fprintf(stderr, + "kcmd(socket): All ports in use\n"); + else + perror("kcmd: socket"); + sigsetmask(oldmask); + return (-1); + } + fcntl(s, F_SETOWN, pid); + sin.sin_family = hp->h_addrtype; +#if defined(ultrix) || defined(sun) + bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); +#else + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, hp->h_length); +#endif + sin.sin_port = rport; + if (connect(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + break; + (void) close(s); + if (errno == EADDRINUSE) { + lport--; + continue; + } + /* + * don't wait very long for Kerberos rcmd. + */ + if (errno == ECONNREFUSED && timo <= 4) { + /* sleep(timo); don't wait at all here */ + timo *= 2; + continue; + } +#if !(defined(ultrix) || defined(sun)) + if (hp->h_addr_list[1] != NULL) { + int oerrno = errno; + + fprintf(stderr, + "kcmd: connect to address %s: ", + inet_ntoa(sin.sin_addr)); + errno = oerrno; + perror(NULL); + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], (caddr_t)&sin.sin_addr, + hp->h_length); + fprintf(stderr, "Trying %s...\n", + inet_ntoa(sin.sin_addr)); + continue; + } +#endif /* !(defined(ultrix) || defined(sun)) */ + if (errno != ECONNREFUSED) + perror(hp->h_name); + sigsetmask(oldmask); + return (-1); + } + lport--; + if (fd2p == 0) { + write(s, "", 1); + lport = 0; + } else { + char num[8]; + int s2 = getport(&lport), s3; + int len = sizeof(from); + + if (s2 < 0) { + status = -1; + goto bad; + } + listen(s2, 1); + (void) sprintf(num, "%d", lport); + if (write(s, num, strlen(num) + 1) != strlen(num) + 1) { + perror("kcmd(write): setting up stderr"); + (void) close(s2); + status = -1; + goto bad; + } + s3 = accept(s2, (struct sockaddr *)&from, &len); + (void) close(s2); + if (s3 < 0) { + perror("kcmd:accept"); + lport = 0; + status = -1; + goto bad; + } + *fd2p = s3; + from.sin_port = ntohs((u_short)from.sin_port); + if (from.sin_family != AF_INET || + from.sin_port >= IPPORT_RESERVED) { + fprintf(stderr, + "kcmd(socket): protocol failure in circuit setup.\n"); + status = -1; + goto bad2; + } + } + /* + * Kerberos-authenticated service. Don't have to send locuser, + * since its already in the ticket, and we'll extract it on + * the other side. + */ + /* (void) write(s, locuser, strlen(locuser)+1); */ + + /* set up the needed stuff for mutual auth, but only if necessary */ + if (authopts & KOPT_DO_MUTUAL) { + int sin_len; + *faddr = sin; + + sin_len = sizeof(struct sockaddr_in); + if (getsockname(s, (struct sockaddr *)laddr, &sin_len) < 0) { + perror("kcmd(getsockname)"); + status = -1; + goto bad2; + } + } +#ifdef KERBEROS + if ((status = krb_sendauth(authopts, s, ticket, service, *ahost, + realm, (unsigned long) getpid(), msg_data, + cred, schedule, + laddr, + faddr, + "KCMDV0.1")) != KSUCCESS) + goto bad2; +#endif /* KERBEROS */ + + (void) write(s, remuser, strlen(remuser)+1); + (void) write(s, cmd, strlen(cmd)+1); + + if ((rc = read(s, &c, 1)) != 1) { + if (rc == -1) + perror(*ahost); + else + fprintf(stderr,"kcmd: bad connection with remote host\n"); + status = -1; + goto bad2; + } + if (c != '\0') { + while (read(s, &c, 1) == 1) { + (void) write(2, &c, 1); + if (c == '\n') + break; + } + status = -1; + goto bad2; + } + sigsetmask(oldmask); + *sock = s; + return (KSUCCESS); +bad2: + if (lport) + (void) close(*fd2p); +bad: + (void) close(s); + sigsetmask(oldmask); + return (status); +} + +int +getport(alport) + int *alport; +{ + struct sockaddr_in sin; + int s; + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) + return (-1); + for (;;) { + sin.sin_port = htons((u_short)*alport); + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0) + return (s); + if (errno != EADDRINUSE) { + (void) close(s); + return (-1); + } + (*alport)--; +#ifdef ATHENA_COMPAT + if (*alport == IPPORT_RESERVED/2) { +#else + if (*alport == IPPORT_RESERVED) { +#endif + (void) close(s); + errno = EAGAIN; /* close */ + return (-1); + } + } +} + +#endif /* !NeXT || KERBEROS */ diff --git a/rlogin.tproj/krb.h b/rlogin.tproj/krb.h new file mode 100644 index 0000000..10b6dca --- /dev/null +++ b/rlogin.tproj/krb.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)krb.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * XXX + * These should be in a kerberos include file. + */ +void des_clear_key __P(()); +int des_read __P((int, char *, int)); +void des_set_key __P((C_Block, Key_schedule)); +int des_write __P((int, char *, int)); +int krb_net_read __P((int, char *, int)); +char *krb_realmofhost __P((char *)); +int krb_sendauth __P((long, int, KTEXT, char *, char *, char *, + u_long, MSG_DAT *, CREDENTIALS *, Key_schedule, + struct sockaddr_in *, struct sockaddr_in *, char *)); +int krcmd __P((char **, u_short, char *, char *, int *, char *)); +int krcmd_mutual __P((char **, u_short, char *, char *, int *, + char *, CREDENTIALS *, Key_schedule)); diff --git a/rlogin.tproj/krcmd.c b/rlogin.tproj/krcmd.c new file mode 100644 index 0000000..cdbba26 --- /dev/null +++ b/rlogin.tproj/krcmd.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Source: /cvs/Darwin/Commands/NeXT/network_cmds/rlogin.tproj/krcmd.c,v $ + * $Header: /mit/kerberos/ucb/mit/kcmd/RCS/krcmd.c,v 5.1 + * 89/07/25 15:38:44 kfall Exp Locker: kfall $ + * static char *rcsid_kcmd_c = + * "$Header: /mit/kerberos/ucb/mit/kcmd/RCS/krcmd.c,v 5.1 89/07/25 15:38:44 + * kfall Exp Locker: kfall $"; + */ + +#ifdef KERBEROS +#include +#ifdef CRYPT +#include +#endif + +#include + +#include +#include + +#include + +#define SERVICE_NAME "rcmd" + +int kcmd __P((int *, char **, u_short, char *, char *, char *, int *, + KTEXT, char *, char *, CREDENTIALS *, Key_schedule, MSG_DAT *, + struct sockaddr_in *, struct sockaddr_in *, long)); + +/* + * krcmd: simplified version of Athena's "kcmd" + * returns a socket attached to the destination, -1 or krb error on error + * if fd2p is non-NULL, another socket is filled in for it + */ + +int +krcmd(ahost, rport, remuser, cmd, fd2p, realm) + char **ahost; + u_short rport; + char *remuser, *cmd; + int *fd2p; + char *realm; +{ + int sock = -1, err = 0; + KTEXT_ST ticket; + long authopts = 0L; + + err = kcmd( + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + &ticket, + SERVICE_NAME, + realm, + (CREDENTIALS *) NULL, /* credentials not used */ + (bit_64 *) NULL, /* key schedule not used */ + (MSG_DAT *) NULL, /* MSG_DAT not used */ + (struct sockaddr_in *) NULL, /* local addr not used */ + (struct sockaddr_in *) NULL, /* foreign addr not used */ + authopts + ); + + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + fprintf(stderr, "krcmd: %s\n", krb_err_txt[err]); + return(-1); + } + if (err < 0) + return(-1); + return(sock); +} + +#ifdef CRYPT +int +krcmd_mutual(ahost, rport, remuser, cmd, fd2p, realm, cred, sched) + char **ahost; + u_short rport; + char *remuser, *cmd; + int *fd2p; + char *realm; + CREDENTIALS *cred; + Key_schedule sched; +{ + int sock, err; + KTEXT_ST ticket; + MSG_DAT msg_dat; + struct sockaddr_in laddr, faddr; + long authopts = KOPT_DO_MUTUAL; + + err = kcmd( + &sock, + ahost, + rport, + NULL, /* locuser not used */ + remuser, + cmd, + fd2p, + &ticket, + SERVICE_NAME, + realm, + cred, /* filled in */ + sched, /* filled in */ + &msg_dat, /* filled in */ + &laddr, /* filled in */ + &faddr, /* filled in */ + authopts + ); + + if (err > KSUCCESS && err < MAX_KRB_ERRORS) { + fprintf(stderr, "krcmd_mutual: %s\n", krb_err_txt[err]); + return(-1); + } + + if (err < 0) + return (-1); + return(sock); +} +#endif /* CRYPT */ +#endif /* KERBEROS */ diff --git a/rlogin.tproj/rlogin.1 b/rlogin.tproj/rlogin.1 new file mode 100644 index 0000000..979658a --- /dev/null +++ b/rlogin.tproj/rlogin.1 @@ -0,0 +1,188 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rlogin.1 8.2 (Berkeley) 4/29/95 +.\" +.Dd April 29, 1995 +.Dt RLOGIN 1 +.Os BSD 4.2 +.Sh NAME +.Nm rlogin +.Nd remote login +.Sh SYNOPSIS +.Nm rlogin +.Op Fl 8EKLdx +.Op Fl e Ar char +.Op Fl k Ar realm +.Op Fl l Ar username +.Ar host +.Nm rlogin +.Op Fl 8EKLdx +.Op Fl e Ar char +.Op Fl k Ar realm +.Ar username@host +.Sh DESCRIPTION +.Nm Rlogin +starts a terminal session on a remote host +.Ar host . +.Pp +.Nm Rlogin +first attempts to use the Kerberos authorization mechanism, described below. +If the remote host does not supporting Kerberos the standard Berkeley +.Pa rhosts +authorization mechanism is used. +The options are as follows: +.Bl -tag -width flag +.It Fl 8 +The +.Fl 8 +option allows an eight-bit input data path at all times; otherwise +parity bits are stripped except when the remote side's stop and start +characters are other than +^S/^Q . +.It Fl E +The +.Fl E +option stops any character from being recognized as an escape character. +When used with the +.Fl 8 +option, this provides a completely transparent connection. +.It Fl K +The +.Fl K +option turns off all Kerberos authentication. +.It Fl L +The +.Fl L +option allows the rlogin session to be run in ``litout'' (see +.Xr tty 4 ) +mode. +.It Fl d +The +.Fl d +option turns on socket debugging (see +.Xr setsockopt 2 ) +on the TCP sockets used for communication with the remote host. +.It Fl e +The +.Fl e +option allows user specification of the escape character, which is +``~'' by default. +This specification may be as a literal character, or as an octal +value in the form \ennn. +.It Fl k +The +.FL k +option requests rlogin to obtain tickets for the remote host +in realm +.Ar realm +instead of the remote host's realm as determined by +.Xr krb_realmofhost 3 . +.It Fl x +The +.Fl x +option turns on +.Tn DES +encryption for all data passed via the +rlogin session. +This may impact response time and +.Tn CPU +utilization, but provides +increased security. +.El +.Pp +A line of the form ``.'' disconnects from the remote host. +Similarly, the line ``^Z'' will suspend the +.Nm rlogin +session, and ``'' suspends the +send portion of the rlogin, but allows output from the remote system. +By default, the tilde (``~'') character is the escape character, and +normally control-Y (``^Y'') is the delayed-suspend character. +.Pp +All echoing takes place at the remote site, so that (except for delays) +the +.Nm rlogin +is transparent. +Flow control via ^S/^Q and flushing of input and output on interrupts +are handled properly. +.Sh KERBEROS AUTHENTICATION +Each user may have a private authorization list in the file +.Pa .klogin +in their home directory. +Each line in this file should contain a Kerberos principal name of the +form +.Ar principal.instance@realm . +If the originating user is authenticated to one of the principals named +in +.Pa .klogin , +access is granted to the account. +The principal +.Ar accountname.@localrealm +is granted access if +there is no +.Pa .klogin +file. +Otherwise a login and password will be prompted for on the remote machine +as in +.Xr login 1 . +To avoid certain security problems, the +.Pa .klogin +file must be owned by +the remote user. +.Pp +If Kerberos authentication fails, a warning message is printed and the +standard Berkeley +.Nm rlogin +is used instead. +.Sh ENVIRONMENT +The following environment variable is utilized by +.Nm rlogin : +.Bl -tag -width TERM +.It Ev TERM +Determines the user's terminal type. +.El +.Sh SEE ALSO +.Xr rsh 1 , +.Xr kerberos 3 , +.Xr krb_sendauth 3 , +.Xr krb_realmofhost 3 +.Sh HISTORY +The +.Nm rlogin +command appeared in +.Bx 4.2 . +.Sh BUGS +.Nm Rlogin +will be replaced by +.Xr telnet 1 +in the near future. +.Pp +More of the environment should be propagated. diff --git a/rlogin.tproj/rlogin.c b/rlogin.tproj/rlogin.c new file mode 100644 index 0000000..b819699 --- /dev/null +++ b/rlogin.tproj/rlogin.c @@ -0,0 +1,1011 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * rlogin - remote login + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#else +#include +#endif + +#ifdef KERBEROS +#include +#include + +#include "krb.h" + +CREDENTIALS cred; +Key_schedule schedule; +int use_kerberos = 1, doencrypt; +char dst_realm_buf[REALM_SZ], *dest_realm = NULL; +#endif + +#ifndef TIOCPKT_WINDOW +#define TIOCPKT_WINDOW 0x80 +#endif + +/* concession to Sun */ +#ifndef SIGUSR1 +#define SIGUSR1 30 +#endif + +int eight, litout, rem; + +int noescape; +u_char escapechar = '~'; + +#ifdef OLDSUN +struct winsize { + unsigned short ws_row, ws_col; + unsigned short ws_xpixel, ws_ypixel; +}; +#else +#define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) +#endif +struct winsize winsize; + +void catch_child __P((int)); +void copytochild __P((int)); +__dead void doit __P((sigset_t *)); +__dead void done __P((int)); +void echo __P((char)); +u_int getescape __P((char *)); +static void do_exit __P((int)); +void lostpeer __P((int)); +void mode __P((int)); +void msg __P((char *)); +void oob __P((int)); +int reader __P((sigset_t *)); +void sendwindow __P((void)); +void setsignal __P((int)); +int speed __P((int)); +void sigwinch __P((int)); +void stop __P((char)); +__dead void usage __P((void)); +void writer __P((void)); +void writeroob __P((int)); + +#ifdef KERBEROS +void warning __P((const char *, ...)); +#endif +#ifdef OLDSUN +int get_window_size __P((int, struct winsize *)); +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct passwd *pw; + struct servent *sp; + sigset_t smask; + uid_t uid; + int argoff, ch, dflag, one; + char *host, *p, *user, term[1024]; + struct sigaction sa; + + argoff = dflag = 0; + one = 1; + host = user = NULL; + + if (p = strrchr(argv[0], '/')) + ++p; + else + p = argv[0]; + + if (strcmp(p, "rlogin") != 0) + host = p; + + /* handle "rlogin host flags" */ + if (!host && argc > 2 && argv[1][0] != '-') { + host = argv[1]; + argoff = 1; + } + +#ifdef KERBEROS +#define OPTIONS "8EKLde:k:l:x" +#else +#define OPTIONS "8EKLde:l:" +#endif + while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) + switch(ch) { + case '8': + eight = 1; + break; + case 'E': + noescape = 1; + break; + case 'K': +#ifdef KERBEROS + use_kerberos = 0; +#endif + break; + case 'L': + litout = 1; + break; + case 'd': + dflag = 1; + break; + case 'e': + noescape = 0; + escapechar = getescape(optarg); + break; +#ifdef KERBEROS + case 'k': + dest_realm = dst_realm_buf; + (void)strncpy(dest_realm, optarg, REALM_SZ); + break; +#endif + case 'l': + user = optarg; + break; +#ifdef CRYPT +#ifdef KERBEROS + case 'x': + doencrypt = 1; + des_set_key(cred.session, schedule); + break; +#endif +#endif + case '?': + default: + usage(); + } + optind += argoff; + argc -= optind; + argv += optind; + + /* if haven't gotten a host yet, do so */ + if (!host && !(host = *argv++)) + usage(); + + if (*argv) + usage(); + + if (!(pw = getpwuid(uid = getuid()))) + errx(1, "unknown user id."); + /* Accept user1@host format, though "-l user2" overrides user1 */ + p = strchr(host, '@'); + if (p) { + *p = '\0'; + if (!user && p > host) + user = host; + host = p + 1; + if (*host == '\0') + usage(); + } + if (!user) + user = pw->pw_name; + + sp = NULL; +#ifdef KERBEROS + if (use_kerberos) { + sp = getservbyname((doencrypt ? "eklogin" : "klogin"), "tcp"); + if (sp == NULL) { + use_kerberos = 0; + warning("can't get entry for %s/tcp service", + doencrypt ? "eklogin" : "klogin"); + } + } +#endif + if (sp == NULL) + sp = getservbyname("login", "tcp"); + if (sp == NULL) + errx(1, "login/tcp: unknown service."); + + (void)snprintf(term, sizeof(term), "%s/%d", + ((p = getenv("TERM")) ? p : "network"), + speed(0)); + + (void)get_window_size(0, &winsize); + + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = lostpeer; + (void)sigaction(SIGPIPE, &sa, (struct sigaction *) 0); + /* will use SIGUSR1 for window size hack, so hold it off */ + sigemptyset(&smask); + sigaddset(&smask, SIGURG); + sigaddset(&smask, SIGUSR1); + (void)sigprocmask(SIG_SETMASK, &smask, &smask); + /* + * We set SIGURG and SIGUSR1 below so that an + * incoming signal will be held pending rather than being + * discarded. Note that these routines will be ready to get + * a signal by the time that they are unblocked below. + */ + sa.sa_handler = copytochild; + (void)sigaction(SIGURG, &sa, (struct sigaction *) 0); + sa.sa_handler = writeroob; + (void)sigaction(SIGUSR1, &sa, (struct sigaction *) 0); + +#ifdef KERBEROS +try_connect: + if (use_kerberos) { + struct hostent *hp; + + /* Fully qualify hostname (needed for krb_realmofhost). */ + hp = gethostbyname(host); + if (hp != NULL && !(host = strdup(hp->h_name))) + errx(1, "%s", strerror(ENOMEM)); + + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(host); + +#ifdef CRYPT + if (doencrypt) + rem = krcmd_mutual(&host, sp->s_port, user, term, 0, + dest_realm, &cred, schedule); + else +#endif /* CRYPT */ + rem = krcmd(&host, sp->s_port, user, term, 0, + dest_realm); + if (rem < 0) { + use_kerberos = 0; + sp = getservbyname("login", "tcp"); + if (sp == NULL) + errx(1, "unknown service login/tcp."); + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); + goto try_connect; + } + } else { +#ifdef CRYPT + if (doencrypt) + errx(1, "the -x flag requires Kerberos authentication."); +#endif /* CRYPT */ + rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); + } +#else + rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); +#endif /* KERBEROS */ + + if (rem < 0) + exit(1); + + if (dflag && + setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) + warn("setsockopt DEBUG (ignored)"); + one = IPTOS_LOWDELAY; + if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0) + warn("setsockopt TOS (ignored)"); + + (void)setuid(uid); + doit(&smask); + /*NOTREACHED*/ +} + +#if BSD >= 198810 +int +speed(fd) + int fd; +{ + struct termios tt; + + (void)tcgetattr(fd, &tt); + + return ((int) cfgetispeed(&tt)); +} +#else +int speeds[] = { /* for older systems, B0 .. EXTB */ + 0, 50, 75, 110, + 134, 150, 200, 300, + 600, 1200, 1800, 2400, + 4800, 9600, 19200, 38400 +}; + +int +speed(fd) + int fd; +{ + struct termios tt; + + (void)tcgetattr(fd, &tt); + + return (speeds[(int)cfgetispeed(&tt)]); +} +#endif + +pid_t child; +struct termios deftt; +struct termios nott; + +void +doit(smask) + sigset_t *smask; +{ + int i; + struct sigaction sa; + + for (i = 0; i < NCCS; i++) + nott.c_cc[i] = _POSIX_VDISABLE; + tcgetattr(0, &deftt); + nott.c_cc[VSTART] = deftt.c_cc[VSTART]; + nott.c_cc[VSTOP] = deftt.c_cc[VSTOP]; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = SIG_IGN; + (void)sigaction(SIGINT, &sa, (struct sigaction *) 0); + setsignal(SIGHUP); + setsignal(SIGQUIT); + child = fork(); + if (child == -1) { + warn("fork"); + done(1); + } + if (child == 0) { + mode(1); + if (reader(smask) == 0) { + msg("connection closed."); + exit(0); + } + sleep(1); + msg("\007connection closed."); + exit(1); + } + + /* + * We may still own the socket, and may have a pending SIGURG (or might + * receive one soon) that we really want to send to the reader. When + * one of these comes in, the trap copytochild simply copies such + * signals to the child. We can now unblock SIGURG and SIGUSR1 + * that were set above. + */ + (void)sigprocmask(SIG_SETMASK, smask, (sigset_t *) 0); + sa.sa_handler = catch_child; + (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0); + writer(); + msg("closed connection."); + done(0); +} + +/* trap a signal, unless it is being ignored. */ +void +setsignal(sig) + int sig; +{ + struct sigaction sa; + sigset_t sigs; + + sigemptyset(&sigs); + sigaddset(&sigs, sig); + sigprocmask(SIG_BLOCK, &sigs, &sigs); + + sigemptyset(&sa.sa_mask); + sa.sa_handler = do_exit; + sa.sa_flags = SA_RESTART; + (void)sigaction(sig, &sa, &sa); + if (sa.sa_handler == SIG_IGN) + (void)sigaction(sig, &sa, (struct sigaction *) 0); + + (void)sigprocmask(SIG_SETMASK, &sigs, (sigset_t *) 0); +} + +__dead void +done(status) + int status; +{ + pid_t w; + int wstatus; + struct sigaction sa; + + mode(0); + if (child > 0) { + /* make sure catch_child does not snap it up */ + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sa.sa_flags = 0; + (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0); + if (kill(child, SIGKILL) >= 0) + while ((w = wait(&wstatus)) > 0 && w != child) + continue; + } + exit(status); +} + +int dosigwinch; + +/* + * This is called when the reader process gets the out-of-band (urgent) + * request to turn on the window-changing protocol. + */ +void +writeroob(signo) + int signo; +{ + struct sigaction sa; + + if (dosigwinch == 0) { + sendwindow(); + sigemptyset(&sa.sa_mask); + sa.sa_handler = sigwinch; + sa.sa_flags = SA_RESTART; + (void)sigaction(SIGWINCH, &sa, (struct sigaction *) 0); + } + dosigwinch = 1; +} + +void +catch_child(signo) + int signo; +{ + int status; + pid_t pid; + + for (;;) { + pid = waitpid(-1, &status, WNOHANG|WUNTRACED); + if (pid == 0) + return; + /* if the child (reader) dies, just quit */ + if (pid < 0 || (pid == child && !WIFSTOPPED(status))) + done(WEXITSTATUS(status) | WTERMSIG(status)); + } + /* NOTREACHED */ +} + +/* + * writer: write to remote: 0 -> line. + * ~. terminate + * ~^Z suspend rlogin process. + * ~ suspend rlogin process, but leave reader alone. + */ +void +writer() +{ + register int bol, local, n; + char c; + + bol = 1; /* beginning of line */ + local = 0; + for (;;) { + n = read(STDIN_FILENO, &c, 1); + if (n <= 0) { + if (n < 0 && errno == EINTR) + continue; + break; + } + /* + * If we're at the beginning of the line and recognize a + * command character, then we echo locally. Otherwise, + * characters are echo'd remotely. If the command character + * is doubled, this acts as a force and local echo is + * suppressed. + */ + if (bol) { + bol = 0; + if (!noescape && c == escapechar) { + local = 1; + continue; + } + } else if (local) { + local = 0; + if (c == '.' || c == deftt.c_cc[VEOF]) { + echo(c); + break; + } + if (c == deftt.c_cc[VSUSP] || c == deftt.c_cc[VDSUSP]) { + bol = 1; + echo(c); + stop(c); + continue; + } + if (c != escapechar) +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + (void)des_write(rem, + (char *)&escapechar, 1); + else +#endif +#endif + (void)write(rem, &escapechar, 1); + } + +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + if (des_write(rem, &c, 1) == 0) { + msg("line gone"); + break; + } + } else +#endif +#endif + if (write(rem, &c, 1) == 0) { + msg("line gone"); + break; + } + bol = c == deftt.c_cc[VKILL] || c == deftt.c_cc[VEOF] || + c == deftt.c_cc[VINTR] || c == deftt.c_cc[VSUSP] || + c == '\r' || c == '\n'; + } +} + +void +#if __STDC__ +echo(register char c) +#else +echo(c) + register char c; +#endif +{ + register char *p; + char buf[8]; + + p = buf; + c &= 0177; + *p++ = escapechar; + if (c < ' ') { + *p++ = '^'; + *p++ = c + '@'; + } else if (c == 0177) { + *p++ = '^'; + *p++ = '?'; + } else + *p++ = c; + *p++ = '\r'; + *p++ = '\n'; + (void)write(STDOUT_FILENO, buf, p - buf); +} + +void +#if __STDC__ +stop(char cmdc) +#else +stop(cmdc) + char cmdc; +#endif +{ + struct sigaction sa; + + mode(0); + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_IGN; + sa.sa_flags = SA_RESTART; + (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0); + (void)kill(cmdc == deftt.c_cc[VSUSP] ? 0 : getpid(), SIGTSTP); + sa.sa_handler = catch_child; + (void)sigaction(SIGCHLD, &sa, (struct sigaction *) 0); + mode(1); + sigwinch(0); /* check for size changes */ +} + +void +sigwinch(signo) + int signo; +{ + struct winsize ws; + + if (dosigwinch && get_window_size(0, &ws) == 0 && + memcmp(&ws, &winsize, sizeof(ws))) { + winsize = ws; + sendwindow(); + } +} + +/* + * Send the window size to the server via the magic escape + */ +void +sendwindow() +{ + struct winsize *wp; + char obuf[4 + sizeof (struct winsize)]; + + wp = (struct winsize *)(obuf+4); + obuf[0] = 0377; + obuf[1] = 0377; + obuf[2] = 's'; + obuf[3] = 's'; + wp->ws_row = htons(winsize.ws_row); + wp->ws_col = htons(winsize.ws_col); + wp->ws_xpixel = htons(winsize.ws_xpixel); + wp->ws_ypixel = htons(winsize.ws_ypixel); + +#ifdef CRYPT +#ifdef KERBEROS + if(doencrypt) + (void)des_write(rem, obuf, sizeof(obuf)); + else +#endif +#endif + (void)write(rem, obuf, sizeof(obuf)); +} + +/* + * reader: read from remote: line -> 1 + */ +#define READING 1 +#define WRITING 2 + +jmp_buf rcvtop; +pid_t ppid; +int rcvcnt, rcvstate; +char rcvbuf[8 * 1024]; + +void +oob(signo) + int signo; +{ + struct termios tt; + int atmark, n, out, rcvd; + char waste[BUFSIZ], mark; + + out = O_RDWR; + rcvd = 0; + while (recv(rem, &mark, 1, MSG_OOB) < 0) { + switch (errno) { + case EWOULDBLOCK: + /* + * Urgent data not here yet. It may not be possible + * to send it yet if we are blocked for output and + * our input buffer is full. + */ + if (rcvcnt < sizeof(rcvbuf)) { + n = read(rem, rcvbuf + rcvcnt, + sizeof(rcvbuf) - rcvcnt); + if (n <= 0) + return; + rcvd += n; + } else { + n = read(rem, waste, sizeof(waste)); + if (n <= 0) + return; + } + continue; + default: + return; + } + } + if (mark & TIOCPKT_WINDOW) { + /* Let server know about window size changes */ + (void)kill(ppid, SIGUSR1); + } + if (!eight && (mark & TIOCPKT_NOSTOP)) { + tcgetattr(0, &tt); + tt.c_iflag &= ~(IXON | IXOFF); + tt.c_cc[VSTOP] = _POSIX_VDISABLE; + tt.c_cc[VSTART] = _POSIX_VDISABLE; + tcsetattr(0, TCSANOW, &tt); + } + if (!eight && (mark & TIOCPKT_DOSTOP)) { + tcgetattr(0, &tt); + tt.c_iflag |= (IXON|IXOFF); + tt.c_cc[VSTOP] = deftt.c_cc[VSTOP]; + tt.c_cc[VSTART] = deftt.c_cc[VSTART]; + tcsetattr(0, TCSANOW, &tt); + } + if (mark & TIOCPKT_FLUSHWRITE) { + (void)ioctl(1, TIOCFLUSH, (char *)&out); + for (;;) { + if (ioctl(rem, SIOCATMARK, &atmark) < 0) { + warn("ioctl SIOCATMARK (ignored)"); + break; + } + if (atmark) + break; + n = read(rem, waste, sizeof (waste)); + if (n <= 0) + break; + } + /* + * Don't want any pending data to be output, so clear the recv + * buffer. If we were hanging on a write when interrupted, + * don't want it to restart. If we were reading, restart + * anyway. + */ + rcvcnt = 0; + longjmp(rcvtop, 1); + } + + /* oob does not do FLUSHREAD (alas!) */ + + /* + * If we filled the receive buffer while a read was pending, longjmp + * to the top to restart appropriately. Don't abort a pending write, + * however, or we won't know how much was written. + */ + if (rcvd && rcvstate == READING) + longjmp(rcvtop, 1); +} + +/* reader: read from remote: line -> 1 */ +int +reader(smask) + sigset_t *smask; +{ + pid_t pid; + int n, remaining; + char *bufp; + struct sigaction sa; + +#if BSD >= 43 || defined(SUNOS4) + pid = getpid(); /* modern systems use positives for pid */ +#else + pid = -getpid(); /* old broken systems use negatives */ +#endif + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = SIG_IGN; + (void)sigaction(SIGTTOU, &sa, (struct sigaction *) 0); + sa.sa_handler = oob; + (void)sigaction(SIGURG, &sa, (struct sigaction *) 0); + ppid = getppid(); + (void)fcntl(rem, F_SETOWN, pid); + (void)setjmp(rcvtop); + (void)sigprocmask(SIG_SETMASK, smask, (sigset_t *) 0); + bufp = rcvbuf; + for (;;) { + while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { + rcvstate = WRITING; + n = write(STDOUT_FILENO, bufp, remaining); + if (n < 0) { + if (errno != EINTR) + return (-1); + continue; + } + bufp += n; + } + bufp = rcvbuf; + rcvcnt = 0; + rcvstate = READING; + +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf)); + else +#endif +#endif + rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); + if (rcvcnt == 0) + return (0); + if (rcvcnt < 0) { + if (errno == EINTR) + continue; + warn("read"); + return (-1); + } + } +} + +void +mode(f) + int f; +{ + struct termios tt; + + switch (f) { + case 0: + tcsetattr(0, TCSADRAIN, &deftt); + break; + case 1: + tt = deftt; + tt.c_oflag &= ~(OPOST); + tt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + tt.c_iflag &= ~(ICRNL); + tt.c_cc[VMIN] = 1; + tt.c_cc[VTIME] = 0; + if (eight) { + tt.c_iflag &= ~(IXON | IXOFF | ISTRIP); + tt.c_cc[VSTOP] = _POSIX_VDISABLE; + tt.c_cc[VSTART] = _POSIX_VDISABLE; + } + /*if (litout) + lflags |= LLITOUT;*/ + tcsetattr(0, TCSADRAIN, &tt); + break; + + default: + return; + } +} + +void +lostpeer(signo) + int signo; +{ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = SIG_IGN; + (void)sigaction(SIGPIPE, &sa, (struct sigaction *) 0); + msg("\007connection closed."); + done(1); +} + +/* copy SIGURGs to the child process. */ +void +copytochild(signo) + int signo; +{ + + (void)kill(child, SIGURG); +} + +static void do_exit(int signo) +{ + exit(signo); +} + +void +msg(str) + char *str; +{ + + (void)fprintf(stderr, "rlogin: %s\r\n", str); +} + +#ifdef KERBEROS +/* VARARGS */ +void +#if __STDC__ +warning(const char *fmt, ...) +#else +warning(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + + (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, ".\n"); +} +#endif + +__dead void +usage() +{ + (void)fprintf(stderr, + "usage: rlogin [ -%s]%s[-e char] [ -l username ] [username@]host\n", +#ifdef KERBEROS +#ifdef CRYPT + "8EKLx", " [-k realm] "); +#else + "8EKL", " [-k realm] "); +#endif +#else + "8EL", " "); +#endif + exit(1); +} + +/* + * The following routine provides compatibility (such as it is) between older + * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. + */ +#ifdef OLDSUN +int +get_window_size(fd, wp) + int fd; + struct winsize *wp; +{ + struct ttysize ts; + int error; + + if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) + return (error); + wp->ws_row = ts.ts_lines; + wp->ws_col = ts.ts_cols; + wp->ws_xpixel = 0; + wp->ws_ypixel = 0; + return (0); +} +#endif + +u_int +getescape(p) + register char *p; +{ + long val; + int len; + + if ((len = strlen(p)) == 1) /* use any single char, including '\' */ + return ((u_int)*p); + /* otherwise, \nnn */ + if (*p == '\\' && len >= 2 && len <= 4) { + val = strtol(++p, NULL, 8); + for (;;) { + if (!*++p) + return ((u_int)val); + if (*p < '0' || *p > '8') + break; + } + } + msg("illegal option value -- e"); + usage(); + /* NOTREACHED */ +} diff --git a/rlogind.tproj/Makefile b/rlogind.tproj/Makefile new file mode 100644 index 0000000..753d291 --- /dev/null +++ b/rlogind.tproj/Makefile @@ -0,0 +1,55 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rlogind + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = pathnames.h + +CFILES = rlogind.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rlogind.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DCRYPT +WINDOWS_PB_CFLAGS = -DCRYPT +PDO_UNIX_PB_CFLAGS = -DCRYPT + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rlogind.tproj/Makefile.postamble b/rlogind.tproj/Makefile.postamble new file mode 100644 index 0000000..046da0d --- /dev/null +++ b/rlogind.tproj/Makefile.postamble @@ -0,0 +1,2 @@ +VPATH += :../rlogin.tproj + diff --git a/rlogind.tproj/Makefile.preamble b/rlogind.tproj/Makefile.preamble new file mode 100644 index 0000000..97bb72e --- /dev/null +++ b/rlogind.tproj/Makefile.preamble @@ -0,0 +1,3 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_OFILES = des_rw.o +-include ../Makefile.include diff --git a/rlogind.tproj/PB.project b/rlogind.tproj/PB.project new file mode 100644 index 0000000..20866a4 --- /dev/null +++ b/rlogind.tproj/PB.project @@ -0,0 +1,41 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (pathnames.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rlogind.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rlogind.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DCRYPT"; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = "-DCRYPT"; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rlogind; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = "-DCRYPT"; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rlogind.tproj/pathnames.h b/rlogind.tproj/pathnames.h new file mode 100644 index 0000000..b9a57fa --- /dev/null +++ b/rlogind.tproj/pathnames.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + */ + +#include + +#define _PATH_LOGIN "/usr/bin/login" diff --git a/rlogind.tproj/rlogind.8 b/rlogind.tproj/rlogind.8 new file mode 100644 index 0000000..9c19933 --- /dev/null +++ b/rlogind.tproj/rlogind.8 @@ -0,0 +1,168 @@ +.\" Copyright (c) 1983, 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rlogind.8 8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt RLOGIND 8 +.Os BSD 4.2 +.Sh NAME +.Nm rlogind +.Nd remote login server +.Sh SYNOPSIS +.Nm rlogind +.Op Fl aln +.Sh DESCRIPTION +.Nm Rlogind +is the server for the +.Xr rlogin 1 +program. The server provides a remote login facility +with authentication based on privileged port numbers from trusted hosts. +.Pp +Options supported by +.Nm rlogind : +.Bl -tag -width Ds +.It Fl a +Ask hostname for verification. +.It Fl l +Prevent any authentication based on the user's +.Dq Pa .rhosts +file, unless the user is logging in as the superuser. +.It Fl n +Disable keep-alive messages. +.El +.Pp +.Nm Rlogind +listens for service requests at the port indicated in +the ``login'' service specification; see +.Xr services 5 . +When a service request is received the following protocol +is initiated: +.Bl -enum +.It +The server checks the client's source port. +If the port is not in the range 512-1023, the server +aborts the connection. +.It +The server checks the client's source address +and requests the corresponding host name (see +.Xr gethostbyaddr 3 , +.Xr hosts 5 +and +.Xr named 8 ) . +If the hostname cannot be determined, +the dot-notation representation of the host address is used. +If the hostname is in the same domain as the server (according to +the last two components of the domain name), +or if the +.Fl a +option is given, +the addresses for the hostname are requested, +verifying that the name and address correspond. +Normal authentication is bypassed if the address verification fails. +.El +.Pp +Once the source port and address have been checked, +.Nm rlogind +proceeds with the authentication process described in +.Xr rshd 8 . +It then allocates a pseudo terminal (see +.Xr pty 4 ) , +and manipulates file descriptors so that the slave +half of the pseudo terminal becomes the +.Em stdin , +.Em stdout , +and +.Em stderr +for a login process. +The login process is an instance of the +.Xr login 1 +program, invoked with the +.Fl f +option if authentication has succeeded. +If automatic authentication fails, the user is +prompted to log in as if on a standard terminal line. +.Pp +The parent of the login process manipulates the master side of +the pseudo terminal, operating as an intermediary +between the login process and the client instance of the +.Xr rlogin +program. In normal operation, the packet protocol described +in +.Xr pty 4 +is invoked to provide +.Ql ^S/^Q +type facilities and propagate +interrupt signals to the remote programs. The login process +propagates the client terminal's baud rate and terminal type, +as found in the environment variable, +.Ql Ev TERM ; +see +.Xr environ 7 . +The screen or window size of the terminal is requested from the client, +and window size changes from the client are propagated to the pseudo terminal. +.Pp +Transport-level keepalive messages are enabled unless the +.Fl n +option is present. +The use of keepalive messages allows sessions to be timed out +if the client crashes or becomes unreachable. +.Sh DIAGNOSTICS +All initial diagnostic messages are indicated +by a leading byte with a value of 1, +after which any network connections are closed. +If there are no errors before +.Xr login +is invoked, a null byte is returned as in indication of success. +.Bl -tag -width Ds +.It Sy Try again. +A +.Xr fork +by the server failed. +.El +.Sh SEE ALSO +.Xr login 1 , +.Xr ruserok 3 , +.Xr rshd 8 +.Sh BUGS +The authentication procedure used here assumes the integrity +of each client machine and the connecting medium. This is +insecure, but is useful in an ``open'' environment. +.Pp +A facility to allow all data exchanges to be encrypted should be +present. +.Pp +A more extensible protocol should be used. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/rlogind.tproj/rlogind.c b/rlogind.tproj/rlogind.c new file mode 100644 index 0000000..4cb0575 --- /dev/null +++ b/rlogind.tproj/rlogind.c @@ -0,0 +1,783 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1983, 1988, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1988, 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rlogind.c 8.2 (Berkeley) 4/28/95"; +#endif /* not lint */ + +/* + * remote login server: + * \0 + * remuser\0 + * locuser\0 + * terminal_type/speed\0 + * data + */ + +#define FD_SETSIZE 16 /* don't need many bits for select */ +#include +#include +#include +#include +#ifdef __APPLE__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +#ifndef TIOCPKT_WINDOW +#define TIOCPKT_WINDOW 0x80 +#endif + +#ifdef KERBEROS +#include +#include +#define SECURE_MESSAGE "This rlogin session is using DES encryption for all transmissions.\r\n" + +AUTH_DAT *kdata; +KTEXT ticket; +u_char auth_buf[sizeof(AUTH_DAT)]; +u_char tick_buf[sizeof(KTEXT_ST)]; +Key_schedule schedule; +int doencrypt, retval, use_kerberos, vacuous; + +#define ARGSTR "alnkvx" +#else +#define ARGSTR "aln" +#endif /* KERBEROS */ + +char *env[2]; +#define NMAX 30 +char lusername[NMAX+1], rusername[NMAX+1]; +static char term[64] = "TERM="; +#define ENVSIZE (sizeof("TERM=")-1) /* skip null for concatenation */ +int keepalive = 1; +int check_all = 0; + +struct passwd *pwd; + +void doit __P((int, struct sockaddr_in *)); +int control __P((int, char *, int)); +void protocol __P((int, int)); +void cleanup __P((int)); +void fatal __P((int, char *, int)); +int do_rlogin __P((struct sockaddr_in *)); +void getstr __P((char *, int, char *)); +void setup_term __P((int)); +int do_krb_login __P((struct sockaddr_in *)); +void usage __P((void)); +int local_domain __P((char *)); +char *topdomain __P((char *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int __check_rhosts_file; + struct sockaddr_in from; + int ch, fromlen, on; + + openlog("rlogind", LOG_PID | LOG_CONS, LOG_AUTH); + + opterr = 0; + while ((ch = getopt(argc, argv, ARGSTR)) != EOF) + switch (ch) { + case 'a': + check_all = 1; + break; + case 'l': + __check_rhosts_file = 0; + break; + case 'n': + keepalive = 0; + break; +#ifdef KERBEROS + case 'k': + use_kerberos = 1; + break; + case 'v': + vacuous = 1; + break; +#ifdef CRYPT + case 'x': + doencrypt = 1; + break; +#endif +#endif + case '?': + default: + usage(); + break; + } + argc -= optind; + argv += optind; + +#ifdef KERBEROS + if (use_kerberos && vacuous) { + usage(); + fatal(STDERR_FILENO, "only one of -k and -v allowed", 0); + } +#endif + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + syslog(LOG_ERR,"Can't get peer name of remote host: %m"); + fatal(STDERR_FILENO, "Can't get peer name of remote host", 1); + } + on = 1; + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); + on = IPTOS_LOWDELAY; + if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + doit(0, &from); +} + +int child; +int netf; +char line[MAXPATHLEN]; +int confirmed; + +struct winsize win = { 0, 0, 0, 0 }; + + +void +doit(f, fromp) + int f; + struct sockaddr_in *fromp; +{ + int master, pid, on = 1; + int authenticated = 0; + register struct hostent *hp; + char hostname[2 * MAXHOSTNAMELEN + 1]; + char c; + + alarm(60); + read(f, &c, 1); + + if (c != 0) + exit(1); +#ifdef KERBEROS + if (vacuous) + fatal(f, "Remote host requires Kerberos authentication", 0); +#endif + + alarm(0); + fromp->sin_port = ntohs((u_short)fromp->sin_port); + hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof(struct in_addr), + fromp->sin_family); + if (hp) + (void)strcpy(hostname, hp->h_name); + else + (void)strcpy(hostname, inet_ntoa(fromp->sin_addr)); + +#ifdef KERBEROS + if (use_kerberos) { + retval = do_krb_login(fromp); + if (retval == 0) + authenticated++; + else if (retval > 0) + fatal(f, krb_err_txt[retval], 0); + write(f, &c, 1); + confirmed = 1; /* we sent the null! */ + } else +#endif + { + if (fromp->sin_family != AF_INET || + fromp->sin_port >= IPPORT_RESERVED || + fromp->sin_port < IPPORT_RESERVED/2) { + syslog(LOG_NOTICE, "Connection from %s on illegal port", + inet_ntoa(fromp->sin_addr)); + fatal(f, "Permission denied", 0); + } +#ifdef IP_OPTIONS + { + u_char optbuf[BUFSIZ/3], *cp; + char lbuf[BUFSIZ], *lp; + int optsize = sizeof(optbuf), ipproto; + struct protoent *ip; + + if ((ip = getprotobyname("ip")) != NULL) + ipproto = ip->p_proto; + else + ipproto = IPPROTO_IP; + if (getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, + &optsize) == 0 && optsize != 0) { + lp = lbuf; + for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) + sprintf(lp, " %2.2x", *cp); + syslog(LOG_NOTICE, + "Connection received using IP options (ignored):%s", + lbuf); + if (setsockopt(0, ipproto, IP_OPTIONS, + (char *)NULL, optsize) != 0) { + syslog(LOG_ERR, + "setsockopt IP_OPTIONS NULL: %m"); + exit(1); + } + } + } +#endif + if (do_rlogin(fromp) == 0) + authenticated++; + } + if (confirmed == 0) { + write(f, "", 1); + confirmed = 1; /* we sent the null! */ + } +#ifdef KERBEROS +#ifdef CRYPT + if (doencrypt) + (void) des_write(f, SECURE_MESSAGE, sizeof(SECURE_MESSAGE) - 1); +#endif +#endif + netf = f; + + pid = forkpty(&master, line, NULL, &win); + if (pid < 0) { + if (errno == ENOENT) + fatal(f, "Out of ptys", 0); + else + fatal(f, "Forkpty", 1); + } + if (pid == 0) { + if (f > 2) /* f should always be 0, but... */ + (void) close(f); + setup_term(0); + if (authenticated) { +#ifdef KERBEROS + if (use_kerberos && (pwd->pw_uid == 0)) + syslog(LOG_INFO|LOG_AUTH, + "ROOT Kerberos login from %s.%s@%s on %s\n", + kdata->pname, kdata->pinst, kdata->prealm, + hostname); +#endif + + execle(_PATH_LOGIN, "login", "-p", + "-h", hostname, "-f", "--", lusername, NULL, env); + } else + execle(_PATH_LOGIN, "login", "-p", + "-h", hostname, "--", lusername, NULL, env); + fatal(STDERR_FILENO, _PATH_LOGIN, 1); + /*NOTREACHED*/ + } +#ifdef CRYPT +#ifdef KERBEROS + /* + * If encrypted, don't turn on NBIO or the des read/write + * routines will croak. + */ + + if (!doencrypt) +#endif +#endif + ioctl(f, FIONBIO, &on); + ioctl(master, FIONBIO, &on); + ioctl(master, TIOCPKT, &on); + signal(SIGCHLD, cleanup); + protocol(f, master); + signal(SIGCHLD, SIG_IGN); + cleanup(0); +} + +char magic[2] = { 0377, 0377 }; +char oobdata[] = {TIOCPKT_WINDOW}; + +/* + * Handle a "control" request (signaled by magic being present) + * in the data stream. For now, we are only willing to handle + * window size changes. + */ +int +control(pty, cp, n) + int pty; + char *cp; + int n; +{ + struct winsize w; + + if (n < 4+sizeof (w) || cp[2] != 's' || cp[3] != 's') + return (0); + oobdata[0] &= ~TIOCPKT_WINDOW; /* we know he heard */ + memmove(&w, cp+4, sizeof(w)); + w.ws_row = ntohs(w.ws_row); + w.ws_col = ntohs(w.ws_col); + w.ws_xpixel = ntohs(w.ws_xpixel); + w.ws_ypixel = ntohs(w.ws_ypixel); + (void)ioctl(pty, TIOCSWINSZ, &w); + return (4+sizeof (w)); +} + +/* + * rlogin "protocol" machine. + */ +void +protocol(f, p) + register int f, p; +{ + char pibuf[1024+1], fibuf[1024], *pbp, *fbp; + register pcc = 0, fcc = 0; + int cc, nfd, n; + char cntl; + + /* + * Must ignore SIGTTOU, otherwise we'll stop + * when we try and set slave pty's window shape + * (our controlling tty is the master pty). + */ + (void) signal(SIGTTOU, SIG_IGN); + send(f, oobdata, 1, MSG_OOB); /* indicate new rlogin */ + if (f > p) + nfd = f + 1; + else + nfd = p + 1; + if (nfd > FD_SETSIZE) { + syslog(LOG_ERR, "select mask too small, increase FD_SETSIZE"); + fatal(f, "internal error (select mask too small)", 0); + } + for (;;) { + fd_set ibits, obits, ebits, *omask; + + FD_ZERO(&ebits); + FD_ZERO(&ibits); + FD_ZERO(&obits); + omask = (fd_set *)NULL; + if (fcc) { + FD_SET(p, &obits); + omask = &obits; + } else + FD_SET(f, &ibits); + if (pcc >= 0) + if (pcc) { + FD_SET(f, &obits); + omask = &obits; + } else + FD_SET(p, &ibits); + FD_SET(p, &ebits); + if ((n = select(nfd, &ibits, omask, &ebits, 0)) < 0) { + if (errno == EINTR) + continue; + fatal(f, "select", 1); + } + if (n == 0) { + /* shouldn't happen... */ + sleep(5); + continue; + } +#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP)) + if (FD_ISSET(p, &ebits)) { + cc = read(p, &cntl, 1); + if (cc == 1 && pkcontrol(cntl)) { + cntl |= oobdata[0]; + send(f, &cntl, 1, MSG_OOB); + if (cntl & TIOCPKT_FLUSHWRITE) { + pcc = 0; + FD_CLR(p, &ibits); + } + } + } + if (FD_ISSET(f, &ibits)) { +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + fcc = des_read(f, fibuf, sizeof(fibuf)); + else +#endif +#endif + fcc = read(f, fibuf, sizeof(fibuf)); + if (fcc < 0 && errno == EWOULDBLOCK) + fcc = 0; + else { + register char *cp; + int left, n; + + if (fcc <= 0) + break; + fbp = fibuf; + + top: + for (cp = fibuf; cp < fibuf+fcc-1; cp++) + if (cp[0] == magic[0] && + cp[1] == magic[1]) { + left = fcc - (cp-fibuf); + n = control(p, cp, left); + if (n) { + left -= n; + if (left > 0) + bcopy(cp+n, cp, left); + fcc -= n; + goto top; /* n^2 */ + } + } + FD_SET(p, &obits); /* try write */ + } + } + + if (FD_ISSET(p, &obits) && fcc > 0) { + cc = write(p, fbp, fcc); + if (cc > 0) { + fcc -= cc; + fbp += cc; + } + } + + if (FD_ISSET(p, &ibits)) { + pcc = read(p, pibuf, sizeof (pibuf)); + pbp = pibuf; + if (pcc < 0 && errno == EWOULDBLOCK) + pcc = 0; + else if (pcc <= 0) + break; + else if (pibuf[0] == 0) { + pbp++, pcc--; +#ifdef CRYPT +#ifdef KERBEROS + if (!doencrypt) +#endif +#endif + FD_SET(f, &obits); /* try write */ + } else { + if (pkcontrol(pibuf[0])) { + pibuf[0] |= oobdata[0]; + send(f, &pibuf[0], 1, MSG_OOB); + } + pcc = 0; + } + } + if ((FD_ISSET(f, &obits)) && pcc > 0) { +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + cc = des_write(f, pbp, pcc); + else +#endif +#endif + cc = write(f, pbp, pcc); + if (cc < 0 && errno == EWOULDBLOCK) { + /* + * This happens when we try write after read + * from p, but some old kernels balk at large + * writes even when select returns true. + */ + if (!FD_ISSET(p, &ibits)) + sleep(5); + continue; + } + if (cc > 0) { + pcc -= cc; + pbp += cc; + } + } + } +} + +void +cleanup(signo) + int signo; +{ + char *p; + + p = line + sizeof(_PATH_DEV) - 1; + if (logout(p)) + logwtmp(p, "", ""); + (void)chmod(line, 0666); + (void)chown(line, 0, 0); + *p = 'p'; + (void)chmod(line, 0666); + (void)chown(line, 0, 0); + shutdown(netf, 2); + exit(1); +} + +void +fatal(f, msg, syserr) + int f; + char *msg; + int syserr; +{ + int len; + char buf[BUFSIZ], *bp = buf; + + /* + * Prepend binary one to message if we haven't sent + * the magic null as confirmation. + */ + if (!confirmed) + *bp++ = '\01'; /* error indicator */ + if (syserr) + len = sprintf(bp, "rlogind: %s: %s.\r\n", + msg, strerror(errno)); + else + len = sprintf(bp, "rlogind: %s.\r\n", msg); + (void) write(f, buf, bp + len - buf); + exit(1); +} + +int +do_rlogin(dest) + struct sockaddr_in *dest; +{ + getstr(rusername, sizeof(rusername), "remuser too long"); + getstr(lusername, sizeof(lusername), "locuser too long"); + getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type too long"); + + pwd = getpwnam(lusername); + if (pwd == NULL) + return (-1); + if (pwd->pw_uid == 0) + return (-1); + /* XXX why don't we syslog() failure? */ + return (iruserok(dest->sin_addr.s_addr, 0, rusername, lusername)); +} + +void +getstr(buf, cnt, errmsg) + char *buf; + int cnt; + char *errmsg; +{ + char c; + + do { + if (read(0, &c, 1) != 1) + exit(1); + if (--cnt < 0) + fatal(STDOUT_FILENO, errmsg, 0); + *buf++ = c; + } while (c != 0); +} + +void +setup_term(fd) + int fd; +{ + register char *cp = index(term+ENVSIZE, '/'); + char *speed; + struct termios tt; + +#ifndef notyet + tcgetattr(fd, &tt); + if (cp) { + *cp++ = '\0'; + speed = cp; + cp = index(speed, '/'); + if (cp) + *cp++ = '\0'; + cfsetspeed(&tt, atoi(speed)); + } + + tt.c_iflag = TTYDEF_IFLAG; + tt.c_oflag = TTYDEF_OFLAG; + tt.c_lflag = TTYDEF_LFLAG; + tcsetattr(fd, TCSAFLUSH, &tt); +#else + if (cp) { + *cp++ = '\0'; + speed = cp; + cp = index(speed, '/'); + if (cp) + *cp++ = '\0'; + tcgetattr(fd, &tt); + cfsetspeed(&tt, atoi(speed)); + tcsetattr(fd, TCSAFLUSH, &tt); + } +#endif + + env[0] = term; + env[1] = 0; +} + +#ifdef KERBEROS +#define VERSION_SIZE 9 + +/* + * Do the remote kerberos login to the named host with the + * given inet address + * + * Return 0 on valid authorization + * Return -1 on valid authentication, no authorization + * Return >0 for error conditions + */ +int +do_krb_login(dest) + struct sockaddr_in *dest; +{ + int rc; + char instance[INST_SZ], version[VERSION_SIZE]; + long authopts = 0L; /* !mutual */ + struct sockaddr_in faddr; + + kdata = (AUTH_DAT *) auth_buf; + ticket = (KTEXT) tick_buf; + + instance[0] = '*'; + instance[1] = '\0'; + +#ifdef CRYPT + if (doencrypt) { + rc = sizeof(faddr); + if (getsockname(0, (struct sockaddr *)&faddr, &rc)) + return (-1); + authopts = KOPT_DO_MUTUAL; + rc = krb_recvauth( + authopts, 0, + ticket, "rcmd", + instance, dest, &faddr, + kdata, "", schedule, version); + des_set_key(kdata->session, schedule); + + } else +#endif + rc = krb_recvauth( + authopts, 0, + ticket, "rcmd", + instance, dest, (struct sockaddr_in *) 0, + kdata, "", (bit_64 *) 0, version); + + if (rc != KSUCCESS) + return (rc); + + getstr(lusername, sizeof(lusername), "locuser"); + /* get the "cmd" in the rcmd protocol */ + getstr(term+ENVSIZE, sizeof(term)-ENVSIZE, "Terminal type"); + + pwd = getpwnam(lusername); + if (pwd == NULL) + return (-1); + + /* returns nonzero for no access */ + if (kuserok(kdata, lusername) != 0) + return (-1); + + return (0); + +} +#endif /* KERBEROS */ + +void +usage() +{ +#ifdef KERBEROS + syslog(LOG_ERR, "usage: rlogind [-aln] [-k | -v]"); +#else + syslog(LOG_ERR, "usage: rlogind [-aln]"); +#endif +} + +/* + * Check whether host h is in our local domain, + * defined as sharing the last two components of the domain part, + * or the entire domain part if the local domain has only one component. + * If either name is unqualified (contains no '.'), + * assume that the host is local, as it will be + * interpreted as such. + */ +int +local_domain(h) + char *h; +{ + char localhost[MAXHOSTNAMELEN]; + char *p1, *p2; + + localhost[0] = 0; + (void) gethostname(localhost, sizeof(localhost)); + p1 = topdomain(localhost); + p2 = topdomain(h); + if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) + return (1); + return (0); +} + +char * +topdomain(h) + char *h; +{ + register char *p; + char *maybe = NULL; + int dots = 0; + + for (p = h + strlen(h); p >= h; p--) { + if (*p == '.') { + if (++dots == 2) + return (p); + maybe = p; + } + } + return (maybe); +} diff --git a/route.tproj/Makefile b/route.tproj/Makefile new file mode 100644 index 0000000..d1a9e0e --- /dev/null +++ b/route.tproj/Makefile @@ -0,0 +1,53 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = route + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = keywords.h + +CFILES = ccitt_addr.c route.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\ + route.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/route.tproj/Makefile.dist b/route.tproj/Makefile.dist new file mode 100644 index 0000000..f7de878 --- /dev/null +++ b/route.tproj/Makefile.dist @@ -0,0 +1,25 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= route +MAN8= route.0 +SRCS= route.c ccitt_addr.c +CFLAGS+=-I. +CLEANFILES+=keywords.h +BINOWN= root +BINMODE=4555 + +all: route ${MAN8} + +keywords.h: keywords + sed -e '/^#/d' -e '/^$$/d' ${.CURDIR}/keywords > _keywords.tmp + tr a-z A-Z < _keywords.tmp | paste _keywords.tmp - | \ + awk '{ \ + if (NF > 1) \ + printf "#define\tK_%s\t%d\n\t{\"%s\", K_%s},\n", \ + $$2, NR, $$1, $$2 }' \ + > ${.TARGET} + rm -f _keywords.tmp + +.include + +route .depend lint tags: keywords.h diff --git a/route.tproj/Makefile.postamble b/route.tproj/Makefile.postamble new file mode 100644 index 0000000..670967c --- /dev/null +++ b/route.tproj/Makefile.postamble @@ -0,0 +1 @@ +INSTALL_PERMISSIONS = 4555 # If set, 'install' chmod's executable to this diff --git a/route.tproj/Makefile.preamble b/route.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/route.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/route.tproj/PB.project b/route.tproj/PB.project new file mode 100644 index 0000000..f27333b --- /dev/null +++ b/route.tproj/PB.project @@ -0,0 +1,43 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + CLASSES = (); + FRAMEWORKS = (); + H_FILES = (keywords.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (ccitt_addr.c, route.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, route.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = route; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_MAINNIB = route; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = route; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_MAINNIB = route; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/route.tproj/ccitt_addr.c b/route.tproj/ccitt_addr.c new file mode 100644 index 0000000..9c57be3 --- /dev/null +++ b/route.tproj/ccitt_addr.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ccitt_addr.c 8.2 (Berkeley) 4/28/95 + */ + +/* + * parse CCITT addresses + * + * Addresses must have the format: [hpr],x121address[,userdata][,protocol] + * items enclosed with square brackets are optional + * 'h' or 'p' means hi priority (packet size = 128; specific to Datapac + * and necessary only for X.25(76) and non-negotiating X.25(80) DTE's) + * 'r' means reverse charge (remote DTE pays for call). + * The x121address consists of an optional netid and dot, followed + * by a dte address. + * + * Frank Pronk + * The University of British Columbia + * Laboratory for Computational Vision + * Copyright (c) 1984 + */ + +#include +#include +#include + +static char *copychar (); + +ccitt_addr (addr, xp) +char *addr; +register struct sockaddr_x25 *xp; +{ + register char *p, *ap, *limit; + int havenet = 0; + + memset(xp, 0, sizeof (*xp)); + xp->x25_family = AF_CCITT; + xp->x25_len = sizeof(*xp); + p = addr; + + /* + * process optional priority and reverse charging flags + */ + + if (*p == 'p' || *p == 'r' || *p == 'h') { + while (*p == 'p' || *p == 'r' || *p == 'h') { + if (*p == 'p' || *p == 'h') + xp->x25_opts.op_psize = X25_PS128; + else if (*p == 'r') + xp->x25_opts.op_flags |= X25_REVERSE_CHARGE; + p++; + } + if (*p != ',') + return (0); + p++; + } + if (*p == '\0') + return (0); + + /* + * [network id:]X.121 address + */ + + ap = xp->x25_addr; + limit = ap + sizeof (xp->x25_addr) - 1; + while (*p) { + if (*p == ',') + break; + if (*p == '.' || *p == ':') { + if (havenet) + return (0); + havenet++; + xp->x25_net = atoi (xp->x25_addr); + p++; + ap = xp->x25_addr; + *ap = '\0'; + } + if (*p < '0' || *p > '9') + return (0); + if (ap >= limit) + return (0); + *ap++ = *p++; + } + if (*p == '\0') + return (1); + + /* + * optional user data, bytes 4 to 16 + */ + + p++; + ap = xp->x25_udata + 4; /* first four bytes are protocol id */ + limit = ap + sizeof (xp->x25_udata) - 4; + xp->x25_udlen = 4; + while (*p) { + if (*p == ',') + break; + if (ap >= limit) + return (0); + p = copychar (p, ap++); + xp->x25_udlen++; + } + if (xp->x25_udlen == 4) + xp->x25_udlen = 0; + if (*p == '\0') + return (1); + + p++; + ap = xp->x25_udata; /* protocol id */ + limit = ap + (xp->x25_udlen ? 4 : sizeof(xp->x25_udata)); + while (*p) { + if (*p == ',') + return (0); + if (ap >= limit) + return (0); + p = copychar (p, ap++); + } + if (xp->x25_udlen == 0) + xp->x25_udlen = ap - xp->x25_udata; + return (1); +} + +static char * +copychar (from, to) +register char *from, *to; +{ + register int n; + + if (*from != '\\' || from[1] < '0' || from[1] > '7') { + *to = *from++; + return (from); + } + n = *++from - '0'; + from++; + if (*from >= '0' && *from <= '7') { + register int n1; + + n = n*8 + *from++ - '0'; + if (*from >= '0' && *from <= '7' && (n1 = n*8 + *from-'0') < 256) { + n = n1; + from++; + } + } + *to = n; + return (from); +} diff --git a/route.tproj/keywords.h b/route.tproj/keywords.h new file mode 100644 index 0000000..bb5eebd --- /dev/null +++ b/route.tproj/keywords.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +#define K_ADD 1 + {"add", K_ADD}, +#define K_BLACKHOLE 2 + {"blackhole", K_BLACKHOLE}, +#define K_CHANGE 3 + {"change", K_CHANGE}, +#define K_CLONING 4 + {"cloning", K_CLONING}, +#define K_DELETE 5 + {"delete", K_DELETE}, +#define K_DST 6 + {"dst", K_DST}, +#define K_EXPIRE 7 + {"expire", K_EXPIRE}, +#define K_FLUSH 8 + {"flush", K_FLUSH}, +#define K_GATEWAY 9 + {"gateway", K_GATEWAY}, +#define K_GENMASK 10 + {"genmask", K_GENMASK}, +#define K_GET 11 + {"get", K_GET}, +#define K_HOST 12 + {"host", K_HOST}, +#define K_HOPCOUNT 13 + {"hopcount", K_HOPCOUNT}, +#define K_IFACE 14 + {"iface", K_IFACE}, +#define K_INTERFACE 15 + {"interface", K_INTERFACE}, +#define K_IFA 16 + {"ifa", K_IFA}, +#define K_IFP 17 + {"ifp", K_IFP}, +#define K_INET 18 + {"inet", K_INET}, +#define K_ISO 19 + {"iso", K_ISO}, +#define K_LINK 20 + {"link", K_LINK}, +#define K_LOCK 21 + {"lock", K_LOCK}, +#define K_LOCKREST 22 + {"lockrest", K_LOCKREST}, +#define K_MASK 23 + {"mask", K_MASK}, +#define K_MONITOR 24 + {"monitor", K_MONITOR}, +#define K_MTU 25 + {"mtu", K_MTU}, +#define K_NET 26 + {"net", K_NET}, +#define K_NETMASK 27 + {"netmask", K_NETMASK}, +#define K_NOSTATIC 28 + {"nostatic", K_NOSTATIC}, +#define K_OSI 29 + {"osi", K_OSI}, +#define K_PROTO1 30 + {"proto1", K_PROTO1}, +#define K_PROTO2 31 + {"proto2", K_PROTO2}, +#define K_RECVPIPE 32 + {"recvpipe", K_RECVPIPE}, +#define K_REJECT 33 + {"reject", K_REJECT}, +#define K_RTT 34 + {"rtt", K_RTT}, +#define K_RTTVAR 35 + {"rttvar", K_RTTVAR}, +#define K_SA 36 + {"sa", K_SA}, +#define K_SENDPIPE 37 + {"sendpipe", K_SENDPIPE}, +#define K_SSTHRESH 38 + {"ssthresh", K_SSTHRESH}, +#define K_STATIC 39 + {"static", K_STATIC}, +#define K_X25 40 + {"x25", K_X25}, +#define K_XNS 41 + {"xns", K_XNS}, +#define K_XRESOLVE 42 + {"xresolve", K_XRESOLVE}, +#define K_LLINFO 43 + {"llinfo", K_LLINFO}, diff --git a/route.tproj/route.8 b/route.tproj/route.8 new file mode 100644 index 0000000..62b9cfe --- /dev/null +++ b/route.tproj/route.8 @@ -0,0 +1,325 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)route.8 8.4 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt ROUTE 8 +.Os BSD 4.4 +.Sh NAME +.Nm route +.Nd manually manipulate the routing tables. +.Sh SYNOPSIS +.Nm route +.Op Fl nqv +.Ar command +.Oo +.Op Ar modifiers +.Ar args +.Oc +.Sh DESCRIPTION +.Nm Route +is a utility used to manually manipulate the network +routing tables. It normally is not needed, as a +system routing table management daemon such as +.Xr routed 8 , +should tend to this task. +.Pp +The +.Nm route : +utility supports a limited number of general options, +but a rich command language, enabling the user to specify +any arbitrary request that could be delivered via the +programmatic interface discussed in +.Xr route 4 . +.Pp +.Bl -tag -width Ds +.It Fl n +Bypasses attempts to print host and network names symbolically +when reporting actions. (The process of translating between symbolic +names and numerical equivalents can be quite time consuming, and +may require correct operation of the network; thus it may be expedient +to forgo this, especially when attempting to repair networking operations), +.It Fl v +(verbose) Print additional details. +.It Fl q +Suppress all output. +.El +.Pp +The +.Nm route : +utility provides six commands: +.Pp +.Bl -tag -width Fl -compact +.It Cm add +Add a route. +.It Cm flush +Remove all routes. +.It Cm delete +Delete a specific route. +.It Cm change +Change aspects of a route (such as its gateway). +.It Cm get +Lookup and display the route for a destination. +.It Cm monitor +Continuously report any changes to the routing information base, +routing lookup misses, or suspected network partitionings. +.El +.Pp +The monitor command has the syntax +.Pp +.Bd -filled -offset indent -compact +.Nm route Op Fl n +.Cm monitor +.Ed +.Pp +The flush command has the syntax +.Pp +.Bd -filled -offset indent -compact +.Nm route Op Fl n +.Cm flush +.Op Ar family +.Ed +.Pp +If the +.Cm flush +command is specified, +.Nm route +will ``flush'' the routing tables of all gateway entries. +When the address family may is specified by any of the +.Fl osi , +.Fl xns , +or +.Fl inet +modifiers, only routes having destinations with addresses in the +delineated family will be deleted. +.Pp +The other commands have the following syntax: +.Pp +.Bd -filled -offset indent -compact +.Nm route Op Fl n +.Ar command +.Op Fl net No \&| Fl host +.Ar destination gateway +.Ed +.Pp +where +.Ar destination +is the destination host or network, +.Ar gateway +is the next-hop intermediary via which packets should be routed. +Routes to a particular host may be distinguished from those to +a network by interpreting the Internet address specified as the +.Ar destination argument. +The optional modifiers +.Fl net +and +.Fl host +force the destination to be interpreted as a network or a host, respectively. +Otherwise, if the +.Ar destination +has a ``local address part'' of +INADDR_ANY , +or if the +.Ar destination +is the symbolic name of a network, then the route is +assumed to be to a network; otherwise, it is presumed to be a +route to a host. +.Pp +For example, +.Li 128.32 +is interpreted as +.Fl host Li 128.0.0.32 ; +.Li 128.32.130 +is interpreted as +.Fl host Li 128.32.0.130 ; +.Fl net Li 128.32 +is interpreted as +.Li 128.32.0.0; +and +.Fl net Li 128.32.130 +is interpreted as +.Li 128.32.130.0 . +.Pp +If the destination is directly reachable +via an interface requiring +no intermediary system to act as a gateway, the +.Fl interface +modifier should be specified; +the gateway given is the address of this host on the common network, +indicating the interface to be used for transmission. +.Pp +The optional modifiers +.Fl xns , +.Fl osi , +and +.Fl link +specify that all subsequent addresses are in the +.Tn XNS +.Tn OSI +address families, +or are specified as link-level addresses, +and the names must be numeric specifications rather than +symbolic names. +.Pp +The optional +.Fl netmask +qualifier is intended +to achieve the effect of an +.Tn OSI +.Tn ESIS +redirect with the netmask option, +or to manually add subnet routes with +netmasks different from that of the implied network interface +(as would otherwise be communicated using the OSPF or ISIS routing protocols). +One specifies an additional ensuing address parameter +(to be interpreted as a network mask). +The implicit network mask generated in the AF_INET case +can be overridden by making sure this option follows the destination parameter. +.Pp +Routes have associated flags which influence operation of the protocols +when sending to destinations matched by the routes. +These flags may be set (or sometimes cleared) +by indicating the following corresponding modifiers: +.Bd -literal +-cloning RTF_CLONING - generates a new route on use +-xresolve RTF_XRESOLVE - emit mesg on use (for external lookup) +-iface ~RTF_GATEWAY - destination is directly reachable +-static RTF_STATIC - manually added route +-nostatic ~RTF_STATIC - pretend route added by kernel or daemon +-reject RTF_REJECT - emit an ICMP unreachable when matched +-blackhole RTF_BLACKHOLE - silently discard pkts (during updates) +-proto1 RTF_PROTO1 - set protocol specific routing flag #1 +-proto2 RTF_PROTO2 - set protocol specific routing flag #2 +-llinfo RTF_LLINFO - validly translates proto addr to link addr +.Ed +.Pp +The optional modifiers +.Fl rtt , +.Fl rttvar , +.Fl sendpipe , +.Fl recvpipe , +.Fl mtu , +.Fl hopcount , +.Fl expire , +and +.Fl ssthresh +provide initial values to quantities maintained in the routing entry +by transport level protocols, such as TCP or TP4. +These may be individually locked by preceding each such modifier to +be locked by +the +.Fl lock +meta-modifier, or one can +specify that all ensuing metrics may be locked by the +.Fl lockrest +meta-modifier. +.Pp +In a +.Cm change +or +.Cm add +command where the destination and gateway are not sufficient to specify +the route (as in the +.Tn ISO +case where several interfaces may have the +same address), the +.Fl ifp +or +.Fl ifa +modifiers may be used to determine the interface or interface address. +.Pp +All symbolic names specified for a +.Ar destination +or +.Ar gateway +are looked up first as a host name using +.Xr gethostbyname 3 . +If this lookup fails, +.Xr getnetbyname 3 +is then used to interpret the name as that of a network. +.Pp +.Nm Route +uses a routing socket and the new message types +RTM_ADD, +RTM_DELETE, +RTM_GET, +and +RTM_CHANGE. +As such, only the super-user may modify +the routing tables. +.ne 1i +.Sh DIAGNOSTICS +.Bl -tag -width Ds +.It Sy "add [host \&| network ] %s: gateway %s flags %x" +The specified route is being added to the tables. The +values printed are from the routing table entry supplied +in the +.Xr ioctl 2 +call. +If the gateway address used was not the primary address of the gateway +(the first one returned by +.Xr gethostbyname 3 ) , +the gateway address is printed numerically as well as symbolically. +.It Sy "delete [ host &| network ] %s: gateway %s flags %x" +As above, but when deleting an entry. +.It Sy "%s %s done" +When the +.Cm flush +command is specified, each routing table entry deleted +is indicated with a message of this form. +.It Sy "Network is unreachable" +An attempt to add a route failed because the gateway listed was not +on a directly-connected network. +The next-hop gateway must be given. +.It Sy "not in table" +A delete operation was attempted for an entry which +wasn't present in the tables. +.It Sy "routing table overflow" +An add operation was attempted, but the system was +low on resources and was unable to allocate memory +to create the new entry. +.El +.Sh SEE ALSO +.Xr netintro 4 , +.Xr route 4 , +.Xr esis 4 , +.Xr routed 8 , +.Xr XNSrouted 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . +.Sh BUGS +The first paragraph may have slightly exaggerated +.Xr routed Ns 's +abilities. diff --git a/route.tproj/route.c b/route.tproj/route.c new file mode 100644 index 0000000..9c53a27 --- /dev/null +++ b/route.tproj/route.c @@ -0,0 +1,1523 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1989, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1983, 1989, 1991, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)route.c 8.3 (Berkeley) 3/19/94"; +#endif +static const char rcsid[] = + "$Id: route.c,v 1.1.1.2 2000/01/11 01:49:18 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#ifdef AT +#include +#endif +#ifdef NS +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct keytab { + char *kt_cp; + int kt_i; +} keywords[] = { +#include "keywords.h" + {0, 0} +}; + +struct ortentry route; +union sockunion { + struct sockaddr sa; + struct sockaddr_in sin; +#ifdef AT + struct sockaddr_at sat; +#endif +#ifdef NS + struct sockaddr_ns sns; +#endif + struct sockaddr_dl sdl; +} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp; + +typedef union sockunion *sup; +int pid, rtm_addrs, uid; +int s; +int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword(); +int iflag, verbose, aflen = sizeof (struct sockaddr_in); +int locking, lockrest, debugonly; +struct rt_metrics rt_metrics; +u_long rtm_inits; +struct in_addr inet_makeaddr(); +#ifdef AT +int atalk_aton __P((const char *, struct at_addr *)); +char *atalk_ntoa __P((struct at_addr)); +#endif +char *routename(), *netname(); +void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf(); +void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr(); +int getaddr(), rtmsg(), x25_makemask(); +extern char *inet_ntoa(), *iso_ntoa(), *link_ntoa(); + +void usage __P((const char *)); + +void +usage(cp) + const char *cp; +{ + if (cp) + warnx("bad keyword: %s", cp); + (void) fprintf(stderr, + "usage: route [-dnqtv] command [[modifiers] args]\n"); + exit(EX_USAGE); + /* NOTREACHED */ +} + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +int +main(argc, argv) + int argc; + char **argv; +{ + int ch; + + if (argc < 2) + usage((char *)NULL); + + while ((ch = getopt(argc, argv, "nqdtv")) != -1) + switch(ch) { + case 'n': + nflag = 1; + break; + case 'q': + qflag = 1; + break; + case 'v': + verbose = 1; + break; + case 't': + tflag = 1; + break; + case 'd': + debugonly = 1; + break; + case '?': + default: + usage((char *)NULL); + } + argc -= optind; + argv += optind; + + pid = getpid(); + uid = getuid(); + if (tflag) + s = open("/dev/null", O_WRONLY, 0); + else + s = socket(PF_ROUTE, SOCK_RAW, 0); + if (s < 0) + err(EX_OSERR, "socket"); + setuid(uid); + if (*argv) + switch (keyword(*argv)) { + case K_GET: + uid = 0; + /* FALLTHROUGH */ + + case K_CHANGE: + case K_ADD: + case K_DELETE: + newroute(argc, argv); + exit(0); + /* NOTREACHED */ + + case K_MONITOR: + monitor(); + /* NOTREACHED */ + + case K_FLUSH: + flushroutes(argc, argv); + exit(0); + /* NOTREACHED */ + } + usage(*argv); + /* NOTREACHED */ +} + +/* + * Purge all entries in the routing tables not + * associated with network interfaces. + */ +void +flushroutes(argc, argv) + int argc; + char *argv[]; +{ + size_t needed; + int mib[6], rlen, seqno; + char *buf, *next, *lim; + register struct rt_msghdr *rtm; + + if (uid) { + errx(EX_NOPERM, "must be root to alter routing table"); + } + shutdown(s, 0); /* Don't want to read back our messages */ + if (argc > 1) { + argv++; + if (argc == 2 && **argv == '-') + switch (keyword(*argv + 1)) { + case K_INET: + af = AF_INET; + break; + +#ifdef + case K_ATALK: + af = AF_APPLETALK; + break; +#endif +#ifdef NS + case K_XNS: + af = AF_NS; + break; +#endif + case K_LINK: + af = AF_LINK; + break; + default: + goto bad; + } else +bad: usage(*argv); + } + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; /* protocol */ + mib[3] = 0; /* wildcard address family */ + mib[4] = NET_RT_DUMP; + mib[5] = 0; /* no flags */ + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + err(EX_OSERR, "route-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + errx(EX_OSERR, "malloc failed"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + err(EX_OSERR, "route-sysctl-get"); + lim = buf + needed; + if (verbose) + (void) printf("Examining routing table from sysctl\n"); + seqno = 0; /* ??? */ + for (next = buf; next < lim; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)next; + if (verbose) + print_rtmsg(rtm, rtm->rtm_msglen); + if ((rtm->rtm_flags & RTF_GATEWAY) == 0) + continue; + if (af) { + struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + + if (sa->sa_family != af) + continue; + } + if (debugonly) + continue; + rtm->rtm_type = RTM_DELETE; + rtm->rtm_seq = seqno; + rlen = write(s, next, rtm->rtm_msglen); + if (rlen < (int)rtm->rtm_msglen) { + warn("write to routing socket"); + (void) printf("got only %d for rlen\n", rlen); + break; + } + seqno++; + if (qflag) + continue; + if (verbose) + print_rtmsg(rtm, rlen); + else { + struct sockaddr *sa = (struct sockaddr *)(rtm + 1); + (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ? + routename(sa) : netname(sa)); + sa = (struct sockaddr *)(sa->sa_len + (char *)sa); + (void) printf("%-20.20s ", routename(sa)); + (void) printf("done\n"); + } + } +} + +char * +routename(sa) + struct sockaddr *sa; +{ + register char *cp; + static char line[MAXHOSTNAMELEN + 1]; + struct hostent *hp; + static char domain[MAXHOSTNAMELEN + 1]; + static int first = 1; +#ifdef NS + char *ns_print(); +#endif + + if (first) { + first = 0; + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (cp = index(domain, '.'))) { + domain[MAXHOSTNAMELEN] = '\0'; + (void) strcpy(domain, cp + 1); + } else + domain[0] = 0; + } + + if (sa->sa_len == 0) + strcpy(line, "default"); + else switch (sa->sa_family) { + + case AF_INET: + { struct in_addr in; + in = ((struct sockaddr_in *)sa)->sin_addr; + + cp = 0; + if (in.s_addr == INADDR_ANY || sa->sa_len < 4) + cp = "default"; + if (cp == 0 && !nflag) { + hp = gethostbyaddr((char *)&in, sizeof (struct in_addr), + AF_INET); + if (hp) { + if ((cp = index(hp->h_name, '.')) && + !strcmp(cp + 1, domain)) + *cp = 0; + cp = hp->h_name; + } + } + if (cp) { + strncpy(line, cp, sizeof(line) - 1); + line[sizeof(line) - 1] = '\0'; + } else { + /* XXX - why not inet_ntoa()? */ +#define C(x) (unsigned)((x) & 0xff) + in.s_addr = ntohl(in.s_addr); + (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), + C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); + } + break; + } +#ifdef AT + case AF_APPLETALK: + (void) snprintf(line, sizeof(line), "atalk %s", + atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + break; +#endif +#ifdef NS + case AF_NS: + return (ns_print((struct sockaddr_ns *)sa)); +#endif + + case AF_LINK: + return (link_ntoa((struct sockaddr_dl *)sa)); + + default: + { u_short *s = (u_short *)sa; + u_short *slim = s + ((sa->sa_len + 1) >> 1); + char *cp = line + sprintf(line, "(%d)", sa->sa_family); + char *cpe = line + sizeof(line); + + while (++s < slim && cp < cpe) /* start with sa->sa_data */ + cp += snprintf(cp, cpe - cp, " %x", *s); + break; + } + } + return (line); +} + +/* + * Return the name of the network whose address is given. + * The address is assumed to be that of a net or subnet, not a host. + */ +char * +netname(sa) + struct sockaddr *sa; +{ + char *cp = 0; + static char line[MAXHOSTNAMELEN + 1]; + struct netent *np = 0; + u_long net, mask; + register u_long i; + int subnetshift; +#ifdef NS + char *ns_print(); +#endif + + switch (sa->sa_family) { + + case AF_INET: + { struct in_addr in; + in = ((struct sockaddr_in *)sa)->sin_addr; + + i = in.s_addr = ntohl(in.s_addr); + if (in.s_addr == 0) + cp = "default"; + else if (!nflag) { + if (IN_CLASSA(i)) { + mask = IN_CLASSA_NET; + subnetshift = 8; + } else if (IN_CLASSB(i)) { + mask = IN_CLASSB_NET; + subnetshift = 8; + } else { + mask = IN_CLASSC_NET; + subnetshift = 4; + } + /* + * If there are more bits than the standard mask + * would suggest, subnets must be in use. + * Guess at the subnet mask, assuming reasonable + * width subnet fields. + */ + while (in.s_addr &~ mask) + mask = (long)mask >> subnetshift; + net = in.s_addr & mask; + while ((mask & 1) == 0) + mask >>= 1, net >>= 1; + np = getnetbyaddr(net, AF_INET); + if (np) + cp = np->n_name; + } + if (cp) + strncpy(line, cp, sizeof(line)); + else if ((in.s_addr & 0xffffff) == 0) + (void) sprintf(line, "%u", C(in.s_addr >> 24)); + else if ((in.s_addr & 0xffff) == 0) + (void) sprintf(line, "%u.%u", C(in.s_addr >> 24), + C(in.s_addr >> 16)); + else if ((in.s_addr & 0xff) == 0) + (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24), + C(in.s_addr >> 16), C(in.s_addr >> 8)); + else + (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), + C(in.s_addr >> 16), C(in.s_addr >> 8), + C(in.s_addr)); + break; + } +#ifdef AT + case AF_APPLETALK: + (void) snprintf(line, sizeof(line), "atalk %s", + atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr)); + break; +#endif +#ifdef NS + case AF_NS: + return (ns_print((struct sockaddr_ns *)sa)); + break; +#endif + + case AF_LINK: + return (link_ntoa((struct sockaddr_dl *)sa)); + + + default: + { u_short *s = (u_short *)sa->sa_data; + u_short *slim = s + ((sa->sa_len + 1)>>1); + char *cp = line + sprintf(line, "af %d:", sa->sa_family); + char *cpe = line + sizeof(line); + + while (s < slim && cp < cpe) + cp += snprintf(cp, cpe - cp, " %x", *s++); + break; + } + } + return (line); +} + +void +set_metric(value, key) + char *value; + int key; +{ + int flag = 0; + u_long noval, *valp = &noval; + + switch (key) { +#define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break + caseof(K_MTU, RTV_MTU, rmx_mtu); + caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount); + caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire); + caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe); + caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe); + caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh); + caseof(K_RTT, RTV_RTT, rmx_rtt); + caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar); + } + rtm_inits |= flag; + if (lockrest || locking) + rt_metrics.rmx_locks |= flag; + if (locking) + locking = 0; + *valp = atoi(value); +} + +void +newroute(argc, argv) + int argc; + register char **argv; +{ + char *cmd, *dest = "", *gateway = "", *err; + int ishost = 0, ret, attempts, oerrno, flags = RTF_STATIC; + int key; + struct hostent *hp = 0; + + if (uid) { + errx(EX_NOPERM, "must be root to alter routing table"); + } + cmd = argv[0]; + if (*cmd != 'g') + shutdown(s, 0); /* Don't want to read back our messages */ + while (--argc > 0) { + if (**(++argv)== '-') { + switch (key = keyword(1 + *argv)) { + case K_LINK: + af = AF_LINK; + aflen = sizeof(struct sockaddr_dl); + break; + case K_INET: + af = AF_INET; + aflen = sizeof(struct sockaddr_in); + break; +#ifdef AT + case K_ATALK: + af = AF_APPLETALK; + aflen = sizeof(struct sockaddr_at); + break; +#endif + case K_SA: + af = PF_ROUTE; + aflen = sizeof(union sockunion); + break; +#ifdef NS + case K_XNS: + af = AF_NS; + aflen = sizeof(struct sockaddr_ns); + break; +#endif + case K_IFACE: + case K_INTERFACE: + iflag++; + break; + case K_NOSTATIC: + flags &= ~RTF_STATIC; + break; + + case K_LLINFO: + flags |= RTF_LLINFO; + break; + + case K_LOCK: + locking = 1; + break; + case K_LOCKREST: + lockrest = 1; + break; + case K_HOST: + forcehost++; + break; + case K_REJECT: + flags |= RTF_REJECT; + break; + case K_BLACKHOLE: + flags |= RTF_BLACKHOLE; + break; + case K_PROTO1: + flags |= RTF_PROTO1; + break; + case K_PROTO2: + flags |= RTF_PROTO2; + break; + case K_CLONING: + flags |= RTF_CLONING; + break; + case K_XRESOLVE: + flags |= RTF_XRESOLVE; + break; + case K_STATIC: + flags |= RTF_STATIC; + break; + case K_IFA: + argc--; + (void) getaddr(RTA_IFA, *++argv, 0); + break; + case K_IFP: + argc--; + (void) getaddr(RTA_IFP, *++argv, 0); + break; + case K_GENMASK: + argc--; + (void) getaddr(RTA_GENMASK, *++argv, 0); + break; + case K_GATEWAY: + argc--; + (void) getaddr(RTA_GATEWAY, *++argv, 0); + break; + case K_DST: + argc--; + ishost = getaddr(RTA_DST, *++argv, &hp); + dest = *argv; + break; + case K_NETMASK: + argc--; + (void) getaddr(RTA_NETMASK, *++argv, 0); + /* FALLTHROUGH */ + case K_NET: + forcenet++; + break; + case K_MTU: + case K_HOPCOUNT: + case K_EXPIRE: + case K_RECVPIPE: + case K_SENDPIPE: + case K_SSTHRESH: + case K_RTT: + case K_RTTVAR: + argc--; + set_metric(*++argv, key); + break; + default: + usage(1+*argv); + } + } else { + if ((rtm_addrs & RTA_DST) == 0) { + dest = *argv; + ishost = getaddr(RTA_DST, *argv, &hp); + } else if ((rtm_addrs & RTA_GATEWAY) == 0) { + gateway = *argv; + (void) getaddr(RTA_GATEWAY, *argv, &hp); + } else { + (void) getaddr(RTA_NETMASK, *argv, 0); + } + } + } + if (forcehost) + ishost = 1; + if (forcenet) + ishost = 0; + flags |= RTF_UP; + if (ishost) + flags |= RTF_HOST; + if (iflag == 0) + flags |= RTF_GATEWAY; + for (attempts = 1; ; attempts++) { + errno = 0; + if ((ret = rtmsg(*cmd, flags)) == 0) + break; + if (errno != ENETUNREACH && errno != ESRCH) + break; + if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) { + hp->h_addr_list++; + bcopy(hp->h_addr_list[0], &so_gate.sin.sin_addr, + MIN(hp->h_length, sizeof(so_gate.sin.sin_addr))); + } else + break; + } + if (*cmd == 'g') + exit(0); + oerrno = errno; + (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest); + if (*gateway) { + (void) printf(": gateway %s", gateway); + if (attempts > 1 && ret == 0 && af == AF_INET) + (void) printf(" (%s)", + inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr)); + } + if (ret == 0) + (void) printf("\n"); + else { + switch (oerrno) { + case ESRCH: + err = "not in table"; + break; + case EBUSY: + err = "entry in use"; + break; + case ENOBUFS: + err = "routing table overflow"; + break; + default: + err = strerror(oerrno); + break; + } + (void) printf(": %s\n", err); + } +} + +void +inet_makenetandmask(net, sin, bits) + u_long net, bits; + register struct sockaddr_in *sin; +{ + u_long addr, mask = 0; + register char *cp; + + rtm_addrs |= RTA_NETMASK; + if (net == 0) + mask = addr = 0; + else if (bits) { + addr = net; + mask = 0xffffffff << (32 - bits); + } else if (net < 128) { + addr = net << IN_CLASSA_NSHIFT; + mask = IN_CLASSA_NET; + } else if (net < 65536) { + addr = net << IN_CLASSB_NSHIFT; + mask = IN_CLASSB_NET; + } else if (net < 16777216L) { + addr = net << IN_CLASSC_NSHIFT; + mask = IN_CLASSC_NET; + } else { + addr = net; + if ((addr & IN_CLASSA_HOST) == 0) + mask = IN_CLASSA_NET; + else if ((addr & IN_CLASSB_HOST) == 0) + mask = IN_CLASSB_NET; + else if ((addr & IN_CLASSC_HOST) == 0) + mask = IN_CLASSC_NET; + else + mask = -1; + } + sin->sin_addr.s_addr = htonl(addr); + sin = &so_mask.sin; + sin->sin_addr.s_addr = htonl(mask); + sin->sin_len = 0; + sin->sin_family = 0; + cp = (char *)(&sin->sin_addr + 1); + while (*--cp == 0 && cp > (char *)sin) + ; + sin->sin_len = 1 + cp - (char *)sin; +} + +/* + * Interpret an argument as a network address of some kind, + * returning 1 if a host address, 0 if a network address. + */ +int +getaddr(which, s, hpp) + int which; + char *s; + struct hostent **hpp; +{ + register sup su; +#ifdef NS + struct ns_addr ns_addr(); +#endif + struct hostent *hp; + struct netent *np; + u_long val; + char *q,qs; + + if (af == 0) { + af = AF_INET; + aflen = sizeof(struct sockaddr_in); + } + rtm_addrs |= which; + switch (which) { + case RTA_DST: + su = &so_dst; + break; + case RTA_GATEWAY: + su = &so_gate; + if (iflag) { + #define MAX_IFACES 400 + int sock; + struct ifreq iflist[MAX_IFACES]; + struct ifconf ifconf; + struct ifreq *ifr, *ifr_end; + struct sockaddr_dl *dl, *sdl = NULL; + + /* Get socket */ + if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) + err(1, "socket"); + + /* Get interface list */ + ifconf.ifc_req = iflist; + ifconf.ifc_len = sizeof(iflist); + if (ioctl(sock, SIOCGIFCONF, &ifconf) < 0) + err(1, "ioctl(SIOCGIFCONF)"); + close(sock); + + /* Look for this interface in the list */ + for (ifr = ifconf.ifc_req, + ifr_end = (struct ifreq *) + (ifconf.ifc_buf + ifconf.ifc_len); + ifr < ifr_end; + ifr = (struct ifreq *) ((char *) &ifr->ifr_addr + + ifr->ifr_addr.sa_len)) { + dl = (struct sockaddr_dl *)&ifr->ifr_addr; + if (ifr->ifr_addr.sa_family == AF_LINK + && (ifr->ifr_flags & IFF_POINTOPOINT) + && !strncmp(s, dl->sdl_data, dl->sdl_nlen) + && s[dl->sdl_nlen] == 0) { + sdl = dl; + break; + } + } + + /* If we found it, then use it */ + if (sdl) { + su->sdl = *sdl; + return(1); + } + } + break; + case RTA_NETMASK: + su = &so_mask; + break; + case RTA_GENMASK: + su = &so_genmask; + break; + case RTA_IFP: + su = &so_ifp; + break; + case RTA_IFA: + su = &so_ifa; + break; + default: + usage("internal error"); + /*NOTREACHED*/ + } + su->sa.sa_len = aflen; + su->sa.sa_family = af; /* cases that don't want it have left already */ + if (strcmp(s, "default") == 0) { + /* + * Default is net 0.0.0.0/0 + */ + switch (which) { + case RTA_DST: + forcenet++; + /* bzero(su, sizeof(*su)); *//* for readability */ + (void) getaddr(RTA_NETMASK, s, 0); + break; +#if 0 + case RTA_NETMASK: + case RTA_GENMASK: + /* bzero(su, sizeof(*su)); *//* for readability */ +#endif + } + return (0); + } + switch (af) { +#ifdef NS + case AF_NS: + if (which == RTA_DST) { + extern short ns_bh[3]; + struct sockaddr_ns *sms = &(so_mask.sns); + bzero((char *)sms, sizeof(*sms)); + sms->sns_family = 0; + sms->sns_len = 6; + sms->sns_addr.x_net = *(union ns_net *)ns_bh; + rtm_addrs |= RTA_NETMASK; + } + su->sns.sns_addr = ns_addr(s); + return (!ns_nullhost(su->sns.sns_addr)); +#endif + +#ifdef AT + case AF_APPLETALK: + if (!atalk_aton(s, &su->sat.sat_addr)) + errx(EX_NOHOST, "bad address: %s", s); + rtm_addrs |= RTA_NETMASK; + return(forcehost || su->sat.sat_addr.s_node != 0); +#endif + case AF_LINK: + link_addr(s, &su->sdl); + return (1); + + + case PF_ROUTE: + su->sa.sa_len = sizeof(*su); + sockaddr(s, &su->sa); + return (1); + + case AF_INET: + default: + break; + } + + if (hpp == NULL) + hpp = &hp; + *hpp = NULL; + + q = strchr(s,'/'); + if (q && which == RTA_DST) { + qs = *q; + *q = '\0'; + if (((val = inet_addr(s)) != INADDR_NONE)) { + inet_makenetandmask( + htonl(val), &su->sin, strtoul(q+1, 0, 0)); + return (0); + } + *q =qs; + } + if (((val = inet_addr(s)) != INADDR_NONE) && + (which != RTA_DST || forcenet == 0)) { + su->sin.sin_addr.s_addr = val; + if (inet_lnaof(su->sin.sin_addr) != INADDR_ANY) + return (1); + else { + val = ntohl(val); + goto netdone; + } + } + if ((val = inet_network(s)) != INADDR_NONE || + (forcehost == 0 && (np = getnetbyname(s)) != NULL && + (val = np->n_net) != 0)) { +netdone: + if (which == RTA_DST) + inet_makenetandmask(val, &su->sin, 0); + return (0); + } + hp = gethostbyname(s); + if (hp) { + *hpp = hp; + su->sin.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (char *)&su->sin.sin_addr, + MIN(hp->h_length, sizeof(su->sin.sin_addr))); + return (1); + } + errx(EX_NOHOST, "bad address: %s", s); +} + + +#ifdef NS +short ns_nullh[] = {0,0,0}; +short ns_bh[] = {-1,-1,-1}; + +char * +ns_print(sns) + struct sockaddr_ns *sns; +{ + struct ns_addr work; + union { union ns_net net_e; u_long long_e; } net; + u_short port; + static char mybuf[50+MAXHOSTNAMELEN], cport[10], chost[25]; + char *host = ""; + register char *p; + register u_char *q; + + work = sns->sns_addr; + port = ntohs(work.x_port); + work.x_port = 0; + net.net_e = work.x_net; + if (ns_nullhost(work) && net.long_e == 0) { + if (!port) + return ("*.*"); + (void) sprintf(mybuf, "*.%XH", port); + return (mybuf); + } + + if (bcmp((char *)ns_bh, (char *)work.x_host.c_host, 6) == 0) + host = "any"; + else if (bcmp((char *)ns_nullh, (char *)work.x_host.c_host, 6) == 0) + host = "*"; + else { + q = work.x_host.c_host; + (void) sprintf(chost, "%02X%02X%02X%02X%02X%02XH", + q[0], q[1], q[2], q[3], q[4], q[5]); + for (p = chost; *p == '0' && p < chost + 12; p++) + /* void */; + host = p; + } + if (port) + (void) sprintf(cport, ".%XH", htons(port)); + else + *cport = 0; + + (void) snprintf(mybuf, sizeof(mybuf), "%lxH.%s%s", + (unsigned long)ntohl(net.long_e), + host, cport); + return (mybuf); +} +#endif + +void +interfaces() +{ + size_t needed; + int mib[6]; + char *buf, *lim, *next; + register struct rt_msghdr *rtm; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; /* protocol */ + mib[3] = 0; /* wildcard address family */ + mib[4] = NET_RT_IFLIST; + mib[5] = 0; /* no flags */ + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + err(EX_OSERR, "route-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + errx(EX_OSERR, "malloc failed"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + err(EX_OSERR, "actual retrieval of interface table"); + lim = buf + needed; + for (next = buf; next < lim; next += rtm->rtm_msglen) { + rtm = (struct rt_msghdr *)next; + print_rtmsg(rtm, rtm->rtm_msglen); + } +} + +void +monitor() +{ + int n; + char msg[2048]; + + verbose = 1; + if (debugonly) { + interfaces(); + exit(0); + } + for(;;) { + n = read(s, msg, 2048); + (void) printf("got message of size %d\n", n); + print_rtmsg((struct rt_msghdr *)msg, n); + } +} + +struct { + struct rt_msghdr m_rtm; + char m_space[512]; +} m_rtmsg; + +int +rtmsg(cmd, flags) + int cmd, flags; +{ + static int seq; + int rlen; + register char *cp = m_rtmsg.m_space; + register int l; + +#define NEXTADDR(w, u) \ + if (rtm_addrs & (w)) {\ + l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\ + if (verbose) sodump(&(u),"u");\ + } + + errno = 0; + bzero((char *)&m_rtmsg, sizeof(m_rtmsg)); + if (cmd == 'a') + cmd = RTM_ADD; + else if (cmd == 'c') + cmd = RTM_CHANGE; + else if (cmd == 'g') { + cmd = RTM_GET; + if (so_ifp.sa.sa_family == 0) { + so_ifp.sa.sa_family = AF_LINK; + so_ifp.sa.sa_len = sizeof(struct sockaddr_dl); + rtm_addrs |= RTA_IFP; + } + } else + cmd = RTM_DELETE; +#define rtm m_rtmsg.m_rtm + rtm.rtm_type = cmd; + rtm.rtm_flags = flags; + rtm.rtm_version = RTM_VERSION; + rtm.rtm_seq = ++seq; + rtm.rtm_addrs = rtm_addrs; + rtm.rtm_rmx = rt_metrics; + rtm.rtm_inits = rtm_inits; + + if (rtm_addrs & RTA_NETMASK) + mask_addr(); + NEXTADDR(RTA_DST, so_dst); + NEXTADDR(RTA_GATEWAY, so_gate); + NEXTADDR(RTA_NETMASK, so_mask); + NEXTADDR(RTA_GENMASK, so_genmask); + NEXTADDR(RTA_IFP, so_ifp); + NEXTADDR(RTA_IFA, so_ifa); + rtm.rtm_msglen = l = cp - (char *)&m_rtmsg; + if (verbose) + print_rtmsg(&rtm, l); + if (debugonly) + return (0); + if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) { + warn("writing to routing socket"); + return (-1); + } + if (cmd == RTM_GET) { + do { + l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg)); + } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid)); + if (l < 0) + warn("read from routing socket"); + else + print_getmsg(&rtm, l); + } +#undef rtm + return (0); +} + +void +mask_addr() +{ + int olen = so_mask.sa.sa_len; + register char *cp1 = olen + (char *)&so_mask, *cp2; + + for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; ) + if (*--cp1 != 0) { + so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask; + break; + } + if ((rtm_addrs & RTA_DST) == 0) + return; + switch (so_dst.sa.sa_family) { +#ifdef NS + case AF_NS: +#endif + case AF_INET: + case AF_APPLETALK: + case 0: + return; + } + cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst; + cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst; + while (cp2 > cp1) + *--cp2 = 0; + cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask; + while (cp1 > so_dst.sa.sa_data) + *--cp1 &= *--cp2; +} + +char *msgtypes[] = { + "", + "RTM_ADD: Add Route", + "RTM_DELETE: Delete Route", + "RTM_CHANGE: Change Metrics or flags", + "RTM_GET: Report Metrics", + "RTM_LOSING: Kernel Suspects Partitioning", + "RTM_REDIRECT: Told to use different route", + "RTM_MISS: Lookup failed on this address", + "RTM_LOCK: fix specified metrics", + "RTM_OLDADD: caused by SIOCADDRT", + "RTM_OLDDEL: caused by SIOCDELRT", + "RTM_RESOLVE: Route created by cloning", + "RTM_NEWADDR: address being added to iface", + "RTM_DELADDR: address being removed from iface", + "RTM_IFINFO: iface status change", + "RTM_NEWMADDR: new multicast group membership on iface", + "RTM_DELMADDR: multicast group membership removed from iface", + 0, +}; + +char metricnames[] = +"\011pksent\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire\2hopcount" +"\1mtu"; +char routeflags[] = +"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE\010MASK_PRESENT" +"\011CLONING\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE\016b016" +"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3\024CHAINDELETE" +"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST"; +char ifnetflags[] = +"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP" +"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1" +"\017LINK2\020MULTICAST"; +char addrnames[] = +"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; + +void +print_rtmsg(rtm, msglen) + register struct rt_msghdr *rtm; + int msglen; +{ + struct if_msghdr *ifm; + struct ifa_msghdr *ifam; +#ifdef RTM_NEWMADDR + struct ifma_msghdr *ifmam; +#endif + + if (verbose == 0) + return; + if (rtm->rtm_version != RTM_VERSION) { + (void) printf("routing message version %d not understood\n", + rtm->rtm_version); + return; + } + (void)printf("%s: len %d, ", msgtypes[rtm->rtm_type], rtm->rtm_msglen); + switch (rtm->rtm_type) { + case RTM_IFINFO: + ifm = (struct if_msghdr *)rtm; + (void) printf("if# %d, flags:", ifm->ifm_index); + bprintf(stdout, ifm->ifm_flags, ifnetflags); + pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); + break; + case RTM_NEWADDR: + case RTM_DELADDR: + ifam = (struct ifa_msghdr *)rtm; + (void) printf("metric %d, flags:", ifam->ifam_metric); + bprintf(stdout, ifam->ifam_flags, routeflags); + pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs); + break; +#ifdef RTM_NEWMADDR + case RTM_NEWMADDR: + case RTM_DELMADDR: + ifmam = (struct ifma_msghdr *)rtm; + pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs); + break; +#endif + default: + (void) printf("pid: %ld, seq %d, errno %d, flags:", + (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); + bprintf(stdout, rtm->rtm_flags, routeflags); + pmsg_common(rtm); + } +} + +void +print_getmsg(rtm, msglen) + register struct rt_msghdr *rtm; + int msglen; +{ + struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL; + struct sockaddr_dl *ifp = NULL; + register struct sockaddr *sa; + register char *cp; + register int i; + + (void) printf(" route to: %s\n", routename(&so_dst)); + if (rtm->rtm_version != RTM_VERSION) { + warnx("routing message version %d not understood", + rtm->rtm_version); + return; + } + if (rtm->rtm_msglen > msglen) { + warnx("message length mismatch, in packet %d, returned %d", + rtm->rtm_msglen, msglen); + } + if (rtm->rtm_errno) { + errno = rtm->rtm_errno; + warn("message indicates error %d", errno); + return; + } + cp = ((char *)(rtm + 1)); + if (rtm->rtm_addrs) + for (i = 1; i; i <<= 1) + if (i & rtm->rtm_addrs) { + sa = (struct sockaddr *)cp; + switch (i) { + case RTA_DST: + dst = sa; + break; + case RTA_GATEWAY: + gate = sa; + break; + case RTA_NETMASK: + mask = sa; + break; + case RTA_IFP: + if (sa->sa_family == AF_LINK && + ((struct sockaddr_dl *)sa)->sdl_nlen) + ifp = (struct sockaddr_dl *)sa; + break; + } + ADVANCE(cp, sa); + } + if (dst && mask) + mask->sa_family = dst->sa_family; /* XXX */ + if (dst) + (void)printf("destination: %s\n", routename(dst)); + if (mask) { + int savenflag = nflag; + + nflag = 1; + (void)printf(" mask: %s\n", routename(mask)); + nflag = savenflag; + } + if (gate && rtm->rtm_flags & RTF_GATEWAY) + (void)printf(" gateway: %s\n", routename(gate)); + if (ifp) + (void)printf(" interface: %.*s\n", + ifp->sdl_nlen, ifp->sdl_data); + (void)printf(" flags: "); + bprintf(stdout, rtm->rtm_flags, routeflags); + +#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ') +#define msec(u) (((u) + 500) / 1000) /* usec to msec */ + + (void) printf("\n%s\n", "\ + recvpipe sendpipe ssthresh rtt,msec rttvar hopcount mtu expire"); + printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE)); + printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE)); + printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH)); + printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT)); + printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rttvar), lock(RTTVAR)); + printf("%8ld%c ", rtm->rtm_rmx.rmx_hopcount, lock(HOPCOUNT)); + printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU)); + if (rtm->rtm_rmx.rmx_expire) + rtm->rtm_rmx.rmx_expire -= time(0); + printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE)); +#undef lock +#undef msec +#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) + if (verbose) + pmsg_common(rtm); + else if (rtm->rtm_addrs &~ RTA_IGN) { + (void) printf("sockaddrs: "); + bprintf(stdout, rtm->rtm_addrs, addrnames); + putchar('\n'); + } +#undef RTA_IGN +} + +void +pmsg_common(rtm) + register struct rt_msghdr *rtm; +{ + (void) printf("\nlocks: "); + bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); + (void) printf(" inits: "); + bprintf(stdout, rtm->rtm_inits, metricnames); + pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs); +} + +void +pmsg_addrs(cp, addrs) + char *cp; + int addrs; +{ + register struct sockaddr *sa; + int i; + + if (addrs == 0) + return; + (void) printf("\nsockaddrs: "); + bprintf(stdout, addrs, addrnames); + (void) putchar('\n'); + for (i = 1; i; i <<= 1) + if (i & addrs) { + sa = (struct sockaddr *)cp; + (void) printf(" %s", routename(sa)); + ADVANCE(cp, sa); + } + (void) putchar('\n'); + (void) fflush(stdout); +} + +void +bprintf(fp, b, s) + register FILE *fp; + register int b; + register u_char *s; +{ + register int i; + int gotsome = 0; + + if (b == 0) + return; + while ((i = *s++) != 0) { + if (b & (1 << (i-1))) { + if (gotsome == 0) + i = '<'; + else + i = ','; + (void) putc(i, fp); + gotsome = 1; + for (; (i = *s) > 32; s++) + (void) putc(i, fp); + } else + while (*s > 32) + s++; + } + if (gotsome) + (void) putc('>', fp); +} + +int +keyword(cp) + char *cp; +{ + register struct keytab *kt = keywords; + + while (kt->kt_cp && strcmp(kt->kt_cp, cp)) + kt++; + return kt->kt_i; +} + +void +sodump(su, which) + register sup su; + char *which; +{ + switch (su->sa.sa_family) { + case AF_LINK: + (void) printf("%s: link %s; ", + which, link_ntoa(&su->sdl)); + break; + case AF_INET: + (void) printf("%s: inet %s; ", + which, inet_ntoa(su->sin.sin_addr)); + break; +#ifdef AT + case AF_APPLETALK: + (void) printf("%s: atalk %s; ", + which, atalk_ntoa(su->sat.sat_addr)); + break; +#endif +#ifdef NS + case AF_NS: + (void) printf("%s: xns %s; ", + which, ns_ntoa(su->sns.sns_addr)); + break; +#endif + } + (void) fflush(stdout); +} + +/* States*/ +#define VIRGIN 0 +#define GOTONE 1 +#define GOTTWO 2 +/* Inputs */ +#define DIGIT (4*0) +#define END (4*1) +#define DELIM (4*2) + +void +sockaddr(addr, sa) + register char *addr; + register struct sockaddr *sa; +{ + register char *cp = (char *)sa; + int size = sa->sa_len; + char *cplim = cp + size; + register int byte = 0, state = VIRGIN, new = 0 /* foil gcc */; + + bzero(cp, size); + cp++; + do { + if ((*addr >= '0') && (*addr <= '9')) { + new = *addr - '0'; + } else if ((*addr >= 'a') && (*addr <= 'f')) { + new = *addr - 'a' + 10; + } else if ((*addr >= 'A') && (*addr <= 'F')) { + new = *addr - 'A' + 10; + } else if (*addr == 0) + state |= END; + else + state |= DELIM; + addr++; + switch (state /* | INPUT */) { + case GOTTWO | DIGIT: + *cp++ = byte; /*FALLTHROUGH*/ + case VIRGIN | DIGIT: + state = GOTONE; byte = new; continue; + case GOTONE | DIGIT: + state = GOTTWO; byte = new + (byte << 4); continue; + default: /* | DELIM */ + state = VIRGIN; *cp++ = byte; byte = 0; continue; + case GOTONE | END: + case GOTTWO | END: + *cp++ = byte; /* FALLTHROUGH */ + case VIRGIN | END: + break; + } + break; + } while (cp < cplim); + sa->sa_len = cp - (char *)sa; +} + +#ifdef AT +int +atalk_aton(const char *text, struct at_addr *addr) +{ + u_int net, node; + + if (sscanf(text, "%u.%u", &net, &node) != 2 + || net > 0xffff || node > 0xff) + return(0); + addr->s_net = htons(net); + addr->s_node = node; + return(1); +} + +char * +atalk_ntoa(struct at_addr at) +{ + static char buf[20]; + + (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node); + return(buf); +} +#endif diff --git a/routed.tproj/Makefile b/routed.tproj/Makefile new file mode 100644 index 0000000..78e1951 --- /dev/null +++ b/routed.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = routed + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = af.h defs.h interface.h pathnames.h table.h trace.h + +CFILES = af.c defs.c if.c inet.c input.c main.c output.c startup.c\ + tables.c timer.c trace.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.dist routed.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/routed.tproj/Makefile.dist b/routed.tproj/Makefile.dist new file mode 100644 index 0000000..d9dd7f8 --- /dev/null +++ b/routed.tproj/Makefile.dist @@ -0,0 +1,22 @@ +# @(#)Makefile 8.1 (Berkeley) 6/19/93 + +PROG= routed +SRCS= af.c if.c input.c main.c output.c startup.c tables.c timer.c \ + trace.c inet.c +MAN8= routed.0 +#SUBDIR= query trace +DPADD= ${LIBCOMPAT} +LDADD= -lcompat + +.include + +.if (${MACHINE} == "vax") +# The following can be deleted where not appropriate to use the kernel's +# inline code expansions. +INLINE= /sys/vax/inline/obj/inline +C2= /usr/libexec/c2 +.c.o: + ${CC} -S ${CFLAGS} ${.CURDIR}/${.PREFIX}.c + @${C2} ${.PREFIX}.s | ${INLINE} | ${AS} -o ${.PREFIX}.o + @rm -f ${.PREFIX}.s +.endif diff --git a/routed.tproj/Makefile.preamble b/routed.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/routed.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/routed.tproj/PB.project b/routed.tproj/PB.project new file mode 100644 index 0000000..23f9195 --- /dev/null +++ b/routed.tproj/PB.project @@ -0,0 +1,53 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (af.h, defs.h, interface.h, pathnames.h, table.h, trace.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = ( + af.c, + defs.c, + if.c, + inet.c, + input.c, + main.c, + output.c, + startup.c, + tables.c, + timer.c, + trace.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, routed.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_MAINNIB = routed; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_MAINNIB = routed; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = routed; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_MAINNIB = routed; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/routed.tproj/af.c b/routed.tproj/af.c new file mode 100644 index 0000000..a879b6c --- /dev/null +++ b/routed.tproj/af.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +#include "defs.h" + +/* + * Address family support routines + */ +int inet_hash(), inet_netmatch(), inet_output(), + inet_portmatch(), inet_portcheck(), + inet_checkhost(), inet_rtflags(), inet_sendroute(), inet_canon(); +char *inet_format(); + +#define NIL { 0 } +#define INET \ + { inet_hash, inet_netmatch, inet_output, \ + inet_portmatch, inet_portcheck, inet_checkhost, \ + inet_rtflags, inet_sendroute, inet_canon, \ + inet_format \ + } + +struct afswitch afswitch[AF_MAX] = { + NIL, /* 0- unused */ + NIL, /* 1- Unix domain, unused */ + INET, /* Internet */ +}; + +int af_max = sizeof(afswitch) / sizeof(afswitch[0]); + +struct sockaddr_in inet_default = { +#ifdef RTM_ADD + sizeof (inet_default), +#endif + AF_INET, INADDR_ANY }; + +inet_hash(sin, hp) + register struct sockaddr_in *sin; + struct afhash *hp; +{ + register u_long n; + + n = inet_netof(sin->sin_addr); + if (n) + while ((n & 0xff) == 0) + n >>= 8; + hp->afh_nethash = n; + hp->afh_hosthash = ntohl(sin->sin_addr.s_addr); + hp->afh_hosthash &= 0x7fffffff; +} + +inet_netmatch(sin1, sin2) + struct sockaddr_in *sin1, *sin2; +{ + + return (inet_netof(sin1->sin_addr) == inet_netof(sin2->sin_addr)); +} + +/* + * Verify the message is from the right port. + */ +inet_portmatch(sin) + register struct sockaddr_in *sin; +{ + + return (sin->sin_port == sp->s_port); +} + +/* + * Verify the message is from a "trusted" port. + */ +inet_portcheck(sin) + struct sockaddr_in *sin; +{ + + return (ntohs(sin->sin_port) <= IPPORT_RESERVED); +} + +/* + * Internet output routine. + */ +inet_output(s, flags, sin, size) + int s, flags; + struct sockaddr_in *sin; + int size; +{ + struct sockaddr_in dst; + + dst = *sin; + sin = &dst; + if (sin->sin_port == 0) + sin->sin_port = sp->s_port; + if (sin->sin_len == 0) + sin->sin_len = sizeof (*sin); + if (sendto(s, packet, size, flags, + (struct sockaddr *)sin, sizeof (*sin)) < 0) + perror("sendto"); +} + +/* + * Return 1 if the address is believed + * for an Internet host -- THIS IS A KLUDGE. + */ +inet_checkhost(sin) + struct sockaddr_in *sin; +{ + u_long i = ntohl(sin->sin_addr.s_addr); + +#ifndef IN_EXPERIMENTAL +#define IN_EXPERIMENTAL(i) (((long) (i) & 0xe0000000) == 0xe0000000) +#endif + + if (IN_EXPERIMENTAL(i) || sin->sin_port != 0) + return (0); + if (i != 0 && (i & 0xff000000) == 0) + return (0); + for (i = 0; i < sizeof(sin->sin_zero)/sizeof(sin->sin_zero[0]); i++) + if (sin->sin_zero[i]) + return (0); + return (1); +} + +inet_canon(sin) + struct sockaddr_in *sin; +{ + + sin->sin_port = 0; + sin->sin_len = sizeof(*sin); +} + +char * +inet_format(sin) + struct sockaddr_in *sin; +{ + char *inet_ntoa(); + + return (inet_ntoa(sin->sin_addr)); +} diff --git a/routed.tproj/af.h b/routed.tproj/af.h new file mode 100644 index 0000000..02f48b0 --- /dev/null +++ b/routed.tproj/af.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + +/* + * Routing table management daemon. + */ + +/* + * Per address family routines. + */ +struct afswitch { + int (*af_hash)(); /* returns keys based on address */ + int (*af_netmatch)(); /* verifies net # matching */ + int (*af_output)(); /* interprets address for sending */ + int (*af_portmatch)(); /* packet from some other router? */ + int (*af_portcheck)(); /* packet from privileged peer? */ + int (*af_checkhost)(); /* tells if address is valid */ + int (*af_rtflags)(); /* get flags for route (host or net) */ + int (*af_sendroute)(); /* check bounds of subnet broadcast */ + int (*af_canon)(); /* canonicalize address for compares */ + char *(*af_format)(); /* convert address to string */ +}; + +/* + * Structure returned by af_hash routines. + */ +struct afhash { + u_int afh_hosthash; /* host based hash */ + u_int afh_nethash; /* network based hash */ +}; + +extern struct afswitch afswitch[]; /* table proper */ +extern int af_max; /* number of entries in table */ diff --git a/routed.tproj/defs.c b/routed.tproj/defs.c new file mode 100644 index 0000000..5b176bc --- /dev/null +++ b/routed.tproj/defs.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* NeXT */ +#define EXTERN +#include "defs.h" diff --git a/routed.tproj/defs.h b/routed.tproj/defs.h new file mode 100644 index 0000000..fad0ae1 --- /dev/null +++ b/routed.tproj/defs.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + +/* + * Internal data structure definitions for + * user routing process. Based on Xerox NS + * protocol specs with mods relevant to more + * general addressing scheme. + */ +#include +#include +#include + +#include +#include +#include + +#include +#include + +/* NeXT */ +#ifndef EXTERN +#define EXTERN extern +#endif + +#include "trace.h" +#include "interface.h" +#include "table.h" +#include "af.h" + +/* + * When we find any interfaces marked down we rescan the + * kernel every CHECK_INTERVAL seconds to see if they've + * come up. + */ +#define CHECK_INTERVAL (1*60) + +#define equal(a1, a2) \ + (memcmp((a1), (a2), sizeof (struct sockaddr)) == 0) + +EXTERN struct sockaddr_in addr; /* address of daemon's socket */ + +EXTERN int s; /* source and sink of all data */ +EXTERN int r; /* routing socket */ +EXTERN pid_t pid; /* process id for identifying messages */ +EXTERN uid_t uid; /* user id for identifying messages */ +EXTERN int seqno; /* sequence number for identifying messages */ +EXTERN int kmem; +extern int supplier; /* process should supply updates */ +extern int install; /* if 1 call kernel */ +extern int lookforinterfaces; /* if 1 probe kernel for new up interfaces */ +EXTERN int performnlist; /* if 1 check if /vmunix has changed */ +extern int externalinterfaces; /* # of remote and local interfaces */ +EXTERN struct timeval now; /* current idea of time */ +EXTERN struct timeval lastbcast; /* last time all/changes broadcast */ +EXTERN struct timeval lastfullupdate; /* last time full table broadcast */ +EXTERN struct timeval nextbcast; /* time to wait before changes broadcast */ +EXTERN int needupdate; /* true if we need update at nextbcast */ + +EXTERN char packet[MAXPACKETSIZE+1]; +extern struct rip *msg; + +EXTERN char **argv0; +EXTERN struct servent *sp; + +EXTERN struct in_addr inet_makeaddr(); +EXTERN int inet_addr(); +EXTERN int inet_maskof(); +EXTERN int sndmsg(); +EXTERN int supply(); +EXTERN int cleanup(); + +EXTERN int rtioctl(); +#define ADD 1 +#define DELETE 2 +#define CHANGE 3 diff --git a/routed.tproj/if.c b/routed.tproj/if.c new file mode 100644 index 0000000..5235d58 --- /dev/null +++ b/routed.tproj/if.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +extern struct interface *ifnet; + +/* + * Find the interface with address addr. + */ +struct interface * +if_ifwithaddr(addr) + struct sockaddr *addr; +{ + register struct interface *ifp; + +#define same(a1, a2) \ + (memcmp((a1)->sa_data, (a2)->sa_data, 14) == 0) + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_flags & IFF_REMOTE) + continue; + if (ifp->int_addr.sa_family != addr->sa_family) + continue; + if (same(&ifp->int_addr, addr)) + break; + if ((ifp->int_flags & IFF_BROADCAST) && + same(&ifp->int_broadaddr, addr)) + break; + } + return (ifp); +} + +/* + * Find the point-to-point interface with destination address addr. + */ +struct interface * +if_ifwithdstaddr(addr) + struct sockaddr *addr; +{ + register struct interface *ifp; + + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if ((ifp->int_flags & IFF_POINTOPOINT) == 0) + continue; + if (same(&ifp->int_dstaddr, addr)) + break; + } + return (ifp); +} + +/* + * Find the interface on the network + * of the specified address. + */ +struct interface * +if_ifwithnet(addr) + register struct sockaddr *addr; +{ + register struct interface *ifp; + register int af = addr->sa_family; + register int (*netmatch)(); + + if (af >= af_max) + return (0); + netmatch = afswitch[af].af_netmatch; + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_flags & IFF_REMOTE) + continue; + if (af != ifp->int_addr.sa_family) + continue; + if ((*netmatch)(addr, &ifp->int_addr)) + break; + } + return (ifp); +} + +/* + * Find an interface from which the specified address + * should have come from. Used for figuring out which + * interface a packet came in on -- for tracing. + */ +struct interface * +if_iflookup(addr) + struct sockaddr *addr; +{ + register struct interface *ifp, *maybe; + register int af = addr->sa_family; + register int (*netmatch)(); + + if (af >= af_max) + return (0); + maybe = 0; + netmatch = afswitch[af].af_netmatch; + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_addr.sa_family != af) + continue; + if (same(&ifp->int_addr, addr)) + break; + if ((ifp->int_flags & IFF_BROADCAST) && + same(&ifp->int_broadaddr, addr)) + break; + if ((ifp->int_flags & IFF_POINTOPOINT) && + same(&ifp->int_dstaddr, addr)) + break; + if (maybe == 0 && (*netmatch)(addr, &ifp->int_addr)) + maybe = ifp; + } + if (ifp == 0) + ifp = maybe; + return (ifp); +} diff --git a/routed.tproj/inet.c b/routed.tproj/inet.c new file mode 100644 index 0000000..ef194a8 --- /dev/null +++ b/routed.tproj/inet.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Temporarily, copy these routines from the kernel, + * as we need to know about subnets. + */ +#include "defs.h" + +extern struct interface *ifnet; + +/* + * Formulate an Internet address from network + host. + */ +__private_extern__ +struct in_addr +inet_makeaddr(net, host) + u_long net, host; +{ + register struct interface *ifp; + register u_long mask; + u_long addr; + + if (IN_CLASSA(net)) + mask = IN_CLASSA_HOST; + else if (IN_CLASSB(net)) + mask = IN_CLASSB_HOST; + else + mask = IN_CLASSC_HOST; + for (ifp = ifnet; ifp; ifp = ifp->int_next) + if ((ifp->int_netmask & net) == ifp->int_net) { + mask = ~ifp->int_subnetmask; + break; + } + addr = net | (host & mask); + addr = htonl(addr); + return (*(struct in_addr *)&addr); +} + +/* + * Return the network number from an internet address. + */ +__private_extern__ +inet_netof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + register u_long net; + register struct interface *ifp; + + if (IN_CLASSA(i)) + net = i & IN_CLASSA_NET; + else if (IN_CLASSB(i)) + net = i & IN_CLASSB_NET; + else + net = i & IN_CLASSC_NET; + + /* + * Check whether network is a subnet; + * if so, return subnet number. + */ + for (ifp = ifnet; ifp; ifp = ifp->int_next) + if ((ifp->int_netmask & net) == ifp->int_net) + return (i & ifp->int_subnetmask); + return (net); +} + +/* + * Return the host portion of an internet address. + */ +inet_lnaof(in) + struct in_addr in; +{ + register u_long i = ntohl(in.s_addr); + register u_long net, host; + register struct interface *ifp; + + if (IN_CLASSA(i)) { + net = i & IN_CLASSA_NET; + host = i & IN_CLASSA_HOST; + } else if (IN_CLASSB(i)) { + net = i & IN_CLASSB_NET; + host = i & IN_CLASSB_HOST; + } else { + net = i & IN_CLASSC_NET; + host = i & IN_CLASSC_HOST; + } + + /* + * Check whether network is a subnet; + * if so, use the modified interpretation of `host'. + */ + for (ifp = ifnet; ifp; ifp = ifp->int_next) + if ((ifp->int_netmask & net) == ifp->int_net) + return (host &~ ifp->int_subnetmask); + return (host); +} + +/* + * Return the netmask pertaining to an internet address. + */ +inet_maskof(inaddr) + u_long inaddr; +{ + register u_long i = ntohl(inaddr); + register u_long mask; + register struct interface *ifp; + + if (i == 0) { + mask = 0; + } else if (IN_CLASSA(i)) { + mask = IN_CLASSA_NET; + } else if (IN_CLASSB(i)) { + mask = IN_CLASSB_NET; + } else + mask = IN_CLASSC_NET; + + /* + * Check whether network is a subnet; + * if so, use the modified interpretation of `host'. + */ + for (ifp = ifnet; ifp; ifp = ifp->int_next) + if ((ifp->int_netmask & i) == ifp->int_net) + mask = ifp->int_subnetmask; + return (htonl(mask)); +} + +/* + * Return RTF_HOST if the address is + * for an Internet host, RTF_SUBNET for a subnet, + * 0 for a network. + */ +inet_rtflags(sin) + struct sockaddr_in *sin; +{ + register u_long i = ntohl(sin->sin_addr.s_addr); + register u_long net, host; + register struct interface *ifp; + + if (IN_CLASSA(i)) { + net = i & IN_CLASSA_NET; + host = i & IN_CLASSA_HOST; + } else if (IN_CLASSB(i)) { + net = i & IN_CLASSB_NET; + host = i & IN_CLASSB_HOST; + } else { + net = i & IN_CLASSC_NET; + host = i & IN_CLASSC_HOST; + } + + /* + * Check whether this network is subnetted; + * if so, check whether this is a subnet or a host. + */ + for (ifp = ifnet; ifp; ifp = ifp->int_next) + if (net == ifp->int_net) { + if (host &~ ifp->int_subnetmask) + return (RTF_HOST); + else if (ifp->int_subnetmask != ifp->int_netmask) + return (RTF_SUBNET); + else + return (0); /* network */ + } + if (host == 0) + return (0); /* network */ + else + return (RTF_HOST); +} + +/* + * Return true if a route to subnet/host of route rt should be sent to dst. + * Send it only if dst is on the same logical network if not "internal", + * otherwise only if the route is the "internal" route for the logical net. + */ +inet_sendroute(rt, dst) + struct rt_entry *rt; + struct sockaddr_in *dst; +{ + register u_long r = + ntohl(((struct sockaddr_in *)&rt->rt_dst)->sin_addr.s_addr); + register u_long d = ntohl(dst->sin_addr.s_addr); + + if (IN_CLASSA(r)) { + if ((r & IN_CLASSA_NET) == (d & IN_CLASSA_NET)) { + if ((r & IN_CLASSA_HOST) == 0) + return ((rt->rt_state & RTS_INTERNAL) == 0); + return (1); + } + if (r & IN_CLASSA_HOST) + return (0); + return ((rt->rt_state & RTS_INTERNAL) != 0); + } else if (IN_CLASSB(r)) { + if ((r & IN_CLASSB_NET) == (d & IN_CLASSB_NET)) { + if ((r & IN_CLASSB_HOST) == 0) + return ((rt->rt_state & RTS_INTERNAL) == 0); + return (1); + } + if (r & IN_CLASSB_HOST) + return (0); + return ((rt->rt_state & RTS_INTERNAL) != 0); + } else { + if ((r & IN_CLASSC_NET) == (d & IN_CLASSC_NET)) { + if ((r & IN_CLASSC_HOST) == 0) + return ((rt->rt_state & RTS_INTERNAL) == 0); + return (1); + } + if (r & IN_CLASSC_HOST) + return (0); + return ((rt->rt_state & RTS_INTERNAL) != 0); + } +} diff --git a/routed.tproj/input.c b/routed.tproj/input.c new file mode 100644 index 0000000..d39615f --- /dev/null +++ b/routed.tproj/input.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include + +/* + * Process a newly received packet. + */ +rip_input(from, rip, size) + struct sockaddr *from; + register struct rip *rip; + int size; +{ + register struct rt_entry *rt; + register struct netinfo *n; + register struct interface *ifp; + struct interface *if_ifwithdstaddr(); + int count, changes = 0; + register struct afswitch *afp; + static struct sockaddr badfrom, badfrom2; + + ifp = 0; + TRACE_INPUT(ifp, from, (char *)rip, size); + if (from->sa_family >= af_max || + (afp = &afswitch[from->sa_family])->af_hash == (int (*)())0) { + syslog(LOG_INFO, + "\"from\" address in unsupported address family (%d), cmd %d\n", + from->sa_family, rip->rip_cmd); + return; + } + if (rip->rip_vers == 0) { + syslog(LOG_ERR, + "RIP version 0 packet received from %s! (cmd %d)", + (*afswitch[from->sa_family].af_format)(from), rip->rip_cmd); + return; + } + switch (rip->rip_cmd) { + + case RIPCMD_REQUEST: + n = rip->rip_nets; + count = size - ((char *)n - (char *)rip); + if (count < sizeof (struct netinfo)) + return; + for (; count > 0; n++) { + if (count < sizeof (struct netinfo)) + break; + count -= sizeof (struct netinfo); + +#if BSD < 198810 + if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ + n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); +#else +#define osa(x) ((struct osockaddr *)(&(x))) + n->rip_dst.sa_family = + ntohs(osa(n->rip_dst)->sa_family); + n->rip_dst.sa_len = sizeof(n->rip_dst); +#endif + n->rip_metric = ntohl(n->rip_metric); + /* + * A single entry with sa_family == AF_UNSPEC and + * metric ``infinity'' means ``all routes''. + * We respond to routers only if we are acting + * as a supplier, or to anyone other than a router + * (eg, query). + */ + if (n->rip_dst.sa_family == AF_UNSPEC && + n->rip_metric == HOPCNT_INFINITY && count == 0) { + if (supplier || (*afp->af_portmatch)(from) == 0) + supply(from, 0, 0, 0); + return; + } + if (n->rip_dst.sa_family < af_max && + afswitch[n->rip_dst.sa_family].af_hash) + rt = rtlookup(&n->rip_dst); + else + rt = 0; +#define min(a, b) (a < b ? a : b) + n->rip_metric = rt == 0 ? HOPCNT_INFINITY : + min(rt->rt_metric + 1, HOPCNT_INFINITY); +#if BSD < 198810 + if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ + n->rip_dst.sa_family = htons(n->rip_dst.sa_family); +#else + osa(n->rip_dst)->sa_family = + htons(n->rip_dst.sa_family); +#endif + n->rip_metric = htonl(n->rip_metric); + } + rip->rip_cmd = RIPCMD_RESPONSE; + memmove(packet, rip, size); + (*afp->af_output)(s, 0, from, size); + return; + + case RIPCMD_TRACEON: + case RIPCMD_TRACEOFF: + /* verify message came from a privileged port */ + if ((*afp->af_portcheck)(from) == 0) + return; + if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & + (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || + ifp->int_flags & IFF_PASSIVE) { + syslog(LOG_ERR, "trace command from unknown router, %s", + (*afswitch[from->sa_family].af_format)(from)); + return; + } + ((char *)rip)[size] = '\0'; + if (rip->rip_cmd == RIPCMD_TRACEON) + traceon(rip->rip_tracefile); + else + traceoff(); + return; + + case RIPCMD_RESPONSE: + /* verify message came from a router */ + if ((*afp->af_portmatch)(from) == 0) + return; + (*afp->af_canon)(from); + /* are we talking to ourselves? */ + ifp = if_ifwithaddr(from); + if (ifp) { + if (ifp->int_flags & IFF_PASSIVE) { + syslog(LOG_ERR, + "bogus input (from passive interface, %s)", + (*afswitch[from->sa_family].af_format)(from)); + return; + } + rt = rtfind(from); + if (rt == 0 || ((rt->rt_state & RTS_INTERFACE) == 0) && + rt->rt_metric >= ifp->int_metric) + addrouteforif(ifp); + else + rt->rt_timer = 0; + return; + } + /* + * Update timer for interface on which the packet arrived. + * If from other end of a point-to-point link that isn't + * in the routing tables, (re-)add the route. + */ + if ((rt = rtfind(from)) && + (rt->rt_state & (RTS_INTERFACE | RTS_REMOTE))) + rt->rt_timer = 0; + else if ((ifp = if_ifwithdstaddr(from)) && + (rt == 0 || rt->rt_metric >= ifp->int_metric)) + addrouteforif(ifp); + /* + * "Authenticate" router from which message originated. + * We accept routing packets from routers directly connected + * via broadcast or point-to-point networks, + * and from those listed in /etc/gateways. + */ + if ((ifp = if_iflookup(from)) == 0 || (ifp->int_flags & + (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0 || + ifp->int_flags & IFF_PASSIVE) { + if (memcmp(from, &badfrom, sizeof(badfrom)) != 0) { + syslog(LOG_ERR, + "packet from unknown router, %s", + (*afswitch[from->sa_family].af_format)(from)); + badfrom = *from; + } + return; + } + size -= 4 * sizeof (char); + n = rip->rip_nets; + for (; size > 0; size -= sizeof (struct netinfo), n++) { + if (size < sizeof (struct netinfo)) + break; +#if BSD < 198810 + if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ + n->rip_dst.sa_family = + ntohs(n->rip_dst.sa_family); +#else + n->rip_dst.sa_family = + ntohs(osa(n->rip_dst)->sa_family); + n->rip_dst.sa_len = sizeof(n->rip_dst); +#endif + n->rip_metric = ntohl(n->rip_metric); + if (n->rip_dst.sa_family >= af_max || + (afp = &afswitch[n->rip_dst.sa_family])->af_hash == + (int (*)())0) { + syslog(LOG_INFO, + "route in unsupported address family (%d), from %s (af %d)\n", + n->rip_dst.sa_family, + (*afswitch[from->sa_family].af_format)(from), + from->sa_family); + continue; + } + if (((*afp->af_checkhost)(&n->rip_dst)) == 0) { + syslog(LOG_DEBUG, + "bad host in route from %s (af %d)\n", + (*afswitch[from->sa_family].af_format)(from), + from->sa_family); + continue; + } + if (n->rip_metric == 0 || + (unsigned) n->rip_metric > HOPCNT_INFINITY) { + if (memcmp(from, &badfrom2, + sizeof(badfrom2)) != 0) { + syslog(LOG_ERR, + "bad metric (%d) from %s\n", + n->rip_metric, + (*afswitch[from->sa_family].af_format)(from)); + badfrom2 = *from; + } + continue; + } + /* + * Adjust metric according to incoming interface. + */ + if ((unsigned) n->rip_metric < HOPCNT_INFINITY) + n->rip_metric += ifp->int_metric; + if ((unsigned) n->rip_metric > HOPCNT_INFINITY) + n->rip_metric = HOPCNT_INFINITY; + rt = rtlookup(&n->rip_dst); + if (rt == 0 || + (rt->rt_state & (RTS_INTERNAL|RTS_INTERFACE)) == + (RTS_INTERNAL|RTS_INTERFACE)) { + /* + * If we're hearing a logical network route + * back from a peer to which we sent it, + * ignore it. + */ + if (rt && rt->rt_state & RTS_SUBNET && + (*afp->af_sendroute)(rt, from)) + continue; + if ((unsigned)n->rip_metric < HOPCNT_INFINITY) { + /* + * Look for an equivalent route that + * includes this one before adding + * this route. + */ + rt = rtfind(&n->rip_dst); + if (rt && equal(from, &rt->rt_router)) + continue; + rtadd(&n->rip_dst, from, n->rip_metric, 0); + changes++; + } + continue; + } + + /* + * Update if from gateway and different, + * shorter, or equivalent but old route + * is getting stale. + */ + if (equal(from, &rt->rt_router)) { + if (n->rip_metric != rt->rt_metric) { + rtchange(rt, from, n->rip_metric); + changes++; + rt->rt_timer = 0; + if (rt->rt_metric >= HOPCNT_INFINITY) + rt->rt_timer = + GARBAGE_TIME - EXPIRE_TIME; + } else if (rt->rt_metric < HOPCNT_INFINITY) + rt->rt_timer = 0; + } else if ((unsigned) n->rip_metric < rt->rt_metric || + (rt->rt_metric == n->rip_metric && + rt->rt_timer > (EXPIRE_TIME/2) && + (unsigned) n->rip_metric < HOPCNT_INFINITY)) { + rtchange(rt, from, n->rip_metric); + changes++; + rt->rt_timer = 0; + } + } + break; + } + + /* + * If changes have occurred, and if we have not sent a broadcast + * recently, send a dynamic update. This update is sent only + * on interfaces other than the one on which we received notice + * of the change. If we are within MIN_WAITTIME of a full update, + * don't bother sending; if we just sent a dynamic update + * and set a timer (nextbcast), delay until that time. + * If we just sent a full update, delay the dynamic update. + * Set a timer for a randomized value to suppress additional + * dynamic updates until it expires; if we delayed sending + * the current changes, set needupdate. + */ + if (changes && supplier && + now.tv_sec - lastfullupdate.tv_sec < SUPPLY_INTERVAL-MAX_WAITTIME) { + u_long delay; + extern long random(); + + if (now.tv_sec - lastbcast.tv_sec >= MIN_WAITTIME && + timercmp(&nextbcast, &now, <)) { + if (traceactions) + fprintf(ftrace, "send dynamic update\n"); + toall(supply, RTS_CHANGED, ifp); + lastbcast = now; + needupdate = 0; + nextbcast.tv_sec = 0; + } else { + needupdate++; + if (traceactions) + fprintf(ftrace, "delay dynamic update\n"); + } +#define RANDOMDELAY() (MIN_WAITTIME * 1000000 + \ + (u_long)random() % ((MAX_WAITTIME - MIN_WAITTIME) * 1000000)) + + if (nextbcast.tv_sec == 0) { + delay = RANDOMDELAY(); + if (traceactions) + fprintf(ftrace, + "inhibit dynamic update for %d usec\n", + delay); + nextbcast.tv_sec = delay / 1000000; + nextbcast.tv_usec = delay % 1000000; + timevaladd(&nextbcast, &now); + /* + * If the next possibly dynamic update + * is within MIN_WAITTIME of the next full update, + * force the delay past the full update, + * or we might send a dynamic update just before + * the full update. + */ + if (nextbcast.tv_sec > lastfullupdate.tv_sec + + SUPPLY_INTERVAL - MIN_WAITTIME) + nextbcast.tv_sec = lastfullupdate.tv_sec + + SUPPLY_INTERVAL + 1; + } + } +} diff --git a/routed.tproj/interface.h b/routed.tproj/interface.h new file mode 100644 index 0000000..8e2df84 --- /dev/null +++ b/routed.tproj/interface.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + +/* + * Routing table management daemon. + */ + +/* + * An ``interface'' is similar to an ifnet structure, + * except it doesn't contain q'ing info, and it also + * handles ``logical'' interfaces (remote gateways + * that we want to keep polling even if they go down). + * The list of interfaces which we maintain is used + * in supplying the gratuitous routing table updates. + */ +struct interface { + struct interface *int_next; + struct sockaddr int_addr; /* address on this host */ + union { + struct sockaddr intu_broadaddr; + struct sockaddr intu_dstaddr; + } int_intu; +#define int_broadaddr int_intu.intu_broadaddr /* broadcast address */ +#define int_dstaddr int_intu.intu_dstaddr /* other end of p-to-p link */ + int int_metric; /* init's routing entry */ + int int_flags; /* see below */ + /* START INTERNET SPECIFIC */ + u_long int_net; /* network # */ + u_long int_netmask; /* net mask for addr */ + u_long int_subnet; /* subnet # */ + u_long int_subnetmask; /* subnet mask for addr */ + /* END INTERNET SPECIFIC */ + struct ifdebug int_input, int_output; /* packet tracing stuff */ + int int_ipackets; /* input packets received */ + int int_opackets; /* output packets sent */ + char *int_name; /* from kernel if structure */ + u_short int_transitions; /* times gone up-down */ +}; + +/* + * 0x1 to 0x10 are reused from the kernel's ifnet definitions, + * the others agree with the RTS_ flags defined elsewhere. + */ +#define IFF_UP 0x1 /* interface is up */ +#define IFF_BROADCAST 0x2 /* broadcast address valid */ +#define IFF_DEBUG 0x4 /* turn on debugging */ +#define IFF_LOOPBACK 0x8 /* software loopback net */ +#define IFF_POINTOPOINT 0x10 /* interface is point-to-point link */ + +#define IFF_SUBNET 0x100000 /* interface on subnetted network */ +#define IFF_PASSIVE 0x200000 /* can't tell if up/down */ +#define IFF_INTERFACE 0x400000 /* hardware interface */ +#define IFF_REMOTE 0x800000 /* interface isn't on this machine */ + +struct interface *if_ifwithaddr(); +struct interface *if_ifwithdstaddr(); +struct interface *if_ifwithnet(); +struct interface *if_iflookup(); diff --git a/routed.tproj/main.c b/routed.tproj/main.c new file mode 100644 index 0000000..43597a5 --- /dev/null +++ b/routed.tproj/main.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include +#include + +#include + +#include +#include +#include +#include "pathnames.h" + +int supplier = -1; /* process should supply updates */ +int gateway = 0; /* 1 if we are a gateway to parts beyond */ +int debug = 0; +int bufspace = 127*1024; /* max. input buffer size to request */ + +struct rip *msg = (struct rip *)packet; +void hup(), rtdeleteall(), sigtrace(), timer(); + +main(argc, argv) + int argc; + char *argv[]; +{ + int n, cc, nfd, omask, tflags = 0; + struct sockaddr from; + struct timeval *tvp, waittime; + struct itimerval itval; + register struct rip *query = msg; + fd_set ibits; + u_char retry; + + argv0 = argv; +#if BSD >= 43 + openlog("routed", LOG_PID | LOG_ODELAY, LOG_DAEMON); + setlogmask(LOG_UPTO(LOG_WARNING)); +#else + openlog("routed", LOG_PID); +#define LOG_UPTO(x) (x) +#define setlogmask(x) (x) +#endif + sp = getservbyname("router", "udp"); + if (sp == NULL) { + fprintf(stderr, "routed: router/udp: unknown service\n"); + exit(1); + } + addr.sin_family = AF_INET; + addr.sin_port = sp->s_port; + r = socket(AF_ROUTE, SOCK_RAW, 0); + /* later, get smart about lookingforinterfaces */ + if (r) + shutdown(r, 0); /* for now, don't want reponses */ + else { + fprintf(stderr, "routed: no routing socket\n"); + exit(1); + } + s = getsocket(AF_INET, SOCK_DGRAM, &addr); + if (s < 0) + exit(1); + argv++, argc--; + while (argc > 0 && **argv == '-') { + if (strcmp(*argv, "-s") == 0) { + supplier = 1; + argv++, argc--; + continue; + } + if (strcmp(*argv, "-q") == 0) { + supplier = 0; + argv++, argc--; + continue; + } + if (strcmp(*argv, "-t") == 0) { + tflags++; + setlogmask(LOG_UPTO(LOG_DEBUG)); + argv++, argc--; + continue; + } + if (strcmp(*argv, "-d") == 0) { + debug++; + setlogmask(LOG_UPTO(LOG_DEBUG)); + argv++, argc--; + continue; + } + if (strcmp(*argv, "-g") == 0) { + gateway = 1; + argv++, argc--; + continue; + } + fprintf(stderr, + "usage: routed [ -s ] [ -q ] [ -t ] [ -g ]\n"); + exit(1); + } + + if (debug == 0 && tflags == 0) + daemon(0, 0); + /* + * Any extra argument is considered + * a tracing log file. + */ + if (argc > 0) + traceon(*argv); + while (tflags-- > 0) + bumploglevel(); + + (void) gettimeofday(&now, (struct timezone *)NULL); + /* + * Collect an initial view of the world by + * checking the interface configuration and the gateway kludge + * file. Then, send a request packet on all + * directly connected networks to find out what + * everyone else thinks. + */ + rtinit(); + ifinit(); + gwkludge(); + if (gateway > 0) + rtdefault(); + if (supplier < 0) + supplier = 0; + query->rip_cmd = RIPCMD_REQUEST; + query->rip_vers = RIPVERSION; + if (sizeof(query->rip_nets[0].rip_dst.sa_family) > 1) /* XXX */ + query->rip_nets[0].rip_dst.sa_family = htons((u_short)AF_UNSPEC); + else + query->rip_nets[0].rip_dst.sa_family = AF_UNSPEC; + query->rip_nets[0].rip_metric = htonl((u_long)HOPCNT_INFINITY); + toall(sndmsg); + signal(SIGALRM, timer); + signal(SIGHUP, hup); + signal(SIGTERM, hup); + signal(SIGINT, rtdeleteall); + signal(SIGUSR1, sigtrace); + signal(SIGUSR2, sigtrace); + itval.it_interval.tv_sec = TIMER_RATE; + itval.it_value.tv_sec = TIMER_RATE; + itval.it_interval.tv_usec = 0; + itval.it_value.tv_usec = 0; + srandom(getpid()); + if (setitimer(ITIMER_REAL, &itval, (struct itimerval *)NULL) < 0) + syslog(LOG_ERR, "setitimer: %m\n"); + + FD_ZERO(&ibits); + nfd = s + 1; /* 1 + max(fd's) */ + for (;;) { + FD_SET(s, &ibits); + /* + * If we need a dynamic update that was held off, + * needupdate will be set, and nextbcast is the time + * by which we want select to return. Compute time + * until dynamic update should be sent, and select only + * until then. If we have already passed nextbcast, + * just poll. + */ + if (needupdate) { + waittime = nextbcast; + timevalsub(&waittime, &now); + if (waittime.tv_sec < 0) { + waittime.tv_sec = 0; + waittime.tv_usec = 0; + } + if (traceactions) + fprintf(ftrace, + "select until dynamic update %d/%d sec/usec\n", + waittime.tv_sec, waittime.tv_usec); + tvp = &waittime; + } else + tvp = (struct timeval *)NULL; + n = select(nfd, &ibits, 0, 0, tvp); + if (n <= 0) { + /* + * Need delayed dynamic update if select returned + * nothing and we timed out. Otherwise, ignore + * errors (e.g. EINTR). + */ + if (n < 0) { + if (errno == EINTR) + continue; + syslog(LOG_ERR, "select: %m"); + } + omask = sigblock(sigmask(SIGALRM)); + if (n == 0 && needupdate) { + if (traceactions) + fprintf(ftrace, + "send delayed dynamic update\n"); + (void) gettimeofday(&now, + (struct timezone *)NULL); + toall(supply, RTS_CHANGED, + (struct interface *)NULL); + lastbcast = now; + needupdate = 0; + nextbcast.tv_sec = 0; + } + sigsetmask(omask); + continue; + } + (void) gettimeofday(&now, (struct timezone *)NULL); + omask = sigblock(sigmask(SIGALRM)); +#ifdef doesntwork +/* +printf("s %d, ibits %x index %d, mod %d, sh %x, or %x &ibits %x\n", + s, + ibits.fds_bits[0], + (s)/(sizeof(fd_mask) * 8), + ((s) % (sizeof(fd_mask) * 8)), + (1 << ((s) % (sizeof(fd_mask) * 8))), + ibits.fds_bits[(s)/(sizeof(fd_mask) * 8)] & (1 << ((s) % (sizeof(fd_mask) * 8))), + &ibits + ); +*/ + if (FD_ISSET(s, &ibits)) +#else + if (ibits.fds_bits[s/32] & (1 << s)) +#endif + process(s); + /* handle ICMP redirects */ + sigsetmask(omask); + } +} + +timevaladd(t1, t2) + struct timeval *t1, *t2; +{ + + t1->tv_sec += t2->tv_sec; + if ((t1->tv_usec += t2->tv_usec) > 1000000) { + t1->tv_sec++; + t1->tv_usec -= 1000000; + } +} + +timevalsub(t1, t2) + struct timeval *t1, *t2; +{ + + t1->tv_sec -= t2->tv_sec; + if ((t1->tv_usec -= t2->tv_usec) < 0) { + t1->tv_sec--; + t1->tv_usec += 1000000; + } +} + +process(fd) + int fd; +{ + struct sockaddr from; + int fromlen, cc; + union { + char buf[MAXPACKETSIZE+1]; + struct rip rip; + } inbuf; + + for (;;) { + fromlen = sizeof (from); + cc = recvfrom(fd, &inbuf, sizeof (inbuf), 0, &from, &fromlen); + if (cc <= 0) { + if (cc < 0 && errno != EWOULDBLOCK) + perror("recvfrom"); + break; + } + if (fromlen != sizeof (struct sockaddr_in)) + break; + rip_input(&from, &inbuf.rip, cc); + } +} + +getsocket(domain, type, sin) + int domain, type; + struct sockaddr_in *sin; +{ + int sock, on = 1; + + if ((sock = socket(domain, type, 0)) < 0) { + perror("socket"); + syslog(LOG_ERR, "socket: %m"); + return (-1); + } +#ifdef SO_BROADCAST + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) { + syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); + close(sock); + return (-1); + } +#endif +#ifdef SO_RCVBUF + for (on = bufspace; ; on -= 1024) { + if (setsockopt(sock, SOL_SOCKET, SO_RCVBUF, + &on, sizeof (on)) == 0) + break; + if (on <= 8*1024) { + syslog(LOG_ERR, "setsockopt SO_RCVBUF: %m"); + break; + } + } + if (traceactions) + fprintf(ftrace, "recv buf %d\n", on); +#endif + if (bind(sock, (struct sockaddr *)sin, sizeof (*sin)) < 0) { + perror("bind"); + syslog(LOG_ERR, "bind: %m"); + close(sock); + return (-1); + } + if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) + syslog(LOG_ERR, "fcntl O_NONBLOCK: %m\n"); + return (sock); +} diff --git a/routed.tproj/output.c b/routed.tproj/output.c new file mode 100644 index 0000000..168c320 --- /dev/null +++ b/routed.tproj/output.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +/* + * Apply the function "f" to all non-passive + * interfaces. If the interface supports the + * use of broadcasting use it, otherwise address + * the output to the known router. + */ +toall(f, rtstate, skipif) + int (*f)(); + int rtstate; + struct interface *skipif; +{ + register struct interface *ifp; + register struct sockaddr *dst; + register int flags; + extern struct interface *ifnet; + + for (ifp = ifnet; ifp; ifp = ifp->int_next) { + if (ifp->int_flags & IFF_PASSIVE || ifp == skipif) + continue; + dst = ifp->int_flags & IFF_BROADCAST ? &ifp->int_broadaddr : + ifp->int_flags & IFF_POINTOPOINT ? &ifp->int_dstaddr : + &ifp->int_addr; + flags = ifp->int_flags & IFF_INTERFACE ? MSG_DONTROUTE : 0; + (*f)(dst, flags, ifp, rtstate); + } +} + +/* + * Output a preformed packet. + */ +/*ARGSUSED*/ +sndmsg(dst, flags, ifp, rtstate) + struct sockaddr *dst; + int flags; + struct interface *ifp; + int rtstate; +{ + + (*afswitch[dst->sa_family].af_output)(s, flags, + dst, sizeof (struct rip)); + TRACE_OUTPUT(ifp, dst, sizeof (struct rip)); +} + +/* + * Supply dst with the contents of the routing tables. + * If this won't fit in one packet, chop it up into several. + */ +supply(dst, flags, ifp, rtstate) + struct sockaddr *dst; + int flags; + register struct interface *ifp; + int rtstate; +{ + register struct rt_entry *rt; + register struct netinfo *n = msg->rip_nets; + register struct rthash *rh; + struct rthash *base = hosthash; + int doinghost = 1, size; + int (*output)() = afswitch[dst->sa_family].af_output; + int (*sendroute)() = afswitch[dst->sa_family].af_sendroute; + int npackets = 0; + + msg->rip_cmd = RIPCMD_RESPONSE; + msg->rip_vers = RIPVERSION; + memset(msg->rip_res1, 0, sizeof(msg->rip_res1)); +again: + for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) + for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { + /* + * Don't resend the information on the network + * from which it was received (unless sending + * in response to a query). + */ + if (ifp && rt->rt_ifp == ifp && + (rt->rt_state & RTS_INTERFACE) == 0) + continue; + if (rt->rt_state & RTS_EXTERNAL) + continue; + /* + * For dynamic updates, limit update to routes + * with the specified state. + */ + if (rtstate && (rt->rt_state & rtstate) == 0) + continue; + /* + * Limit the spread of subnet information + * to those who are interested. + */ + if (doinghost == 0 && rt->rt_state & RTS_SUBNET) { + if (rt->rt_dst.sa_family != dst->sa_family) + continue; + if ((*sendroute)(rt, dst) == 0) + continue; + } + size = (char *)n - packet; + if (size > MAXPACKETSIZE - sizeof (struct netinfo)) { + TRACE_OUTPUT(ifp, dst, size); + (*output)(s, flags, dst, size); + /* + * If only sending to ourselves, + * one packet is enough to monitor interface. + */ + if (ifp && (ifp->int_flags & + (IFF_BROADCAST | IFF_POINTOPOINT | IFF_REMOTE)) == 0) + return; + n = msg->rip_nets; + npackets++; + } + n->rip_dst = rt->rt_dst; +#if BSD < 198810 + if (sizeof(n->rip_dst.sa_family) > 1) /* XXX */ + n->rip_dst.sa_family = htons(n->rip_dst.sa_family); +#else +#define osa(x) ((struct osockaddr *)(&(x))) + osa(n->rip_dst)->sa_family = htons(n->rip_dst.sa_family); +#endif + n->rip_metric = htonl(rt->rt_metric); + n++; + } + if (doinghost) { + doinghost = 0; + base = nethash; + goto again; + } + if (n != msg->rip_nets || (npackets == 0 && rtstate == 0)) { + size = (char *)n - packet; + TRACE_OUTPUT(ifp, dst, size); + (*output)(s, flags, dst, size); + } +} diff --git a/routed.tproj/pathnames.h b/routed.tproj/pathnames.h new file mode 100644 index 0000000..12482f7 --- /dev/null +++ b/routed.tproj/pathnames.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + +#include + +#define _PATH_GATEWAYS "/etc/gateways" diff --git a/routed.tproj/routed.8 b/routed.tproj/routed.8 new file mode 100644 index 0000000..8d9ea20 --- /dev/null +++ b/routed.tproj/routed.8 @@ -0,0 +1,358 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)routed.8 8.2 (Berkeley) 12/11/93 +.\" +.Dd December 11, 1993 +.Dt ROUTED 8 +.Os BSD 4.2 +.Sh NAME +.Nm routed +.Nd network routing daemon +.Sh SYNOPSIS +.Nm routed +.Op Fl d +.Op Fl g +.Op Fl q +.Op Fl s +.Op Fl t +.Op Ar logfile +.Sh DESCRIPTION +.Nm Routed +is invoked at boot time to manage the network routing tables. +The routing daemon uses a variant of the Xerox NS Routing +Information Protocol in maintaining up to date kernel routing +table entries. +It used a generalized protocol capable of use with multiple +address types, but is currently used only for Internet routing +within a cluster of networks. +.Pp +In normal operation +.Nm routed +listens on the +.Xr udp 4 +socket for the +.Xr route 8 +service (see +.Xr services 5 ) +for routing information packets. If the host is an +internetwork router, it periodically supplies copies +of its routing tables to any directly connected hosts +and networks. +.Pp +When +.Nm routed +is started, it uses the +.Dv SIOCGIFCONF +.Xr ioctl 2 +to find those +directly connected interfaces configured into the +system and marked ``up'' (the software loopback interface +is ignored). If multiple interfaces +are present, it is assumed that the host will forward packets +between networks. +.Nm Routed +then transmits a +.Em request +packet on each interface (using a broadcast packet if +the interface supports it) and enters a loop, listening +for +.Em request +and +.Em response +packets from other hosts. +.Pp +When a +.Em request +packet is received, +.Nm routed +formulates a reply based on the information maintained in its +internal tables. The +.Em response +packet generated contains a list of known routes, each marked +with a ``hop count'' metric (a count of 16, or greater, is +considered ``infinite''). The metric associated with each +route returned provides a metric +.Em relative to the sender . +.Pp +.Em Response +packets received by +.Nm routed +are used to update the routing tables if one of the following +conditions is satisfied: +.Bl -enum +.It +No routing table entry exists for the destination network +or host, and the metric indicates the destination is ``reachable'' +(i.e. the hop count is not infinite). +.It +The source host of the packet is the same as the router in the +existing routing table entry. That is, updated information is +being received from the very internetwork router through which +packets for the destination are being routed. +.It +The existing entry in the routing table has not been updated for +some time (defined to be 90 seconds) and the route is at least +as cost effective as the current route. +.It +The new route describes a shorter route to the destination than +the one currently stored in the routing tables; the metric of +the new route is compared against the one stored in the table +to decide this. +.El +.Pp +When an update is applied, +.Nm routed +records the change in its internal tables and updates the kernel +routing table. +The change is reflected in the next +.Em response +packet sent. +.Pp +In addition to processing incoming packets, +.Nm routed +also periodically checks the routing table entries. +If an entry has not been updated for 3 minutes, the entry's metric +is set to infinity and marked for deletion. Deletions are delayed +an additional 60 seconds to insure the invalidation is propagated +throughout the local internet. +.Pp +Hosts acting as internetwork routers gratuitously supply their +routing tables every 30 seconds to all directly connected hosts +and networks. +The response is sent to the broadcast address on nets capable of that function, +to the destination address on point-to-point links, and to the router's +own address on other networks. +The normal routing tables are bypassed when sending gratuitous responses. +The reception of responses on each network is used to determine that the +network and interface are functioning correctly. +If no response is received on an interface, another route may be chosen +to route around the interface, or the route may be dropped if no alternative +is available. +.Pp +Options supported by +.Nm routed : +.Bl -tag -width Ds +.It Fl d +Enable additional debugging information to be logged, +such as bad packets received. +.It Fl g +This flag is used on internetwork routers to offer a route +to the ``default'' destination. +This is typically used on a gateway to the Internet, +or on a gateway that uses another routing protocol whose routes +are not reported to other local routers. +.It Fl s +Supplying this +option forces +.Nm routed +to supply routing information whether it is acting as an internetwork +router or not. +This is the default if multiple network interfaces are present, +or if a point-to-point link is in use. +.It Fl q +This +is the opposite of the +.Fl s +option. +.It Fl t +If the +.Fl t +option is specified, all packets sent or received are +printed on the standard output. In addition, +.Nm routed +will not divorce itself from the controlling terminal +so that interrupts from the keyboard will kill the process. +.El +.Pp +Any other argument supplied is interpreted as the name +of file in which +.Nm routed Ns \'s +actions should be logged. This log contains information +about any changes to the routing tables and, if not tracing all packets, +a history of recent messages sent and received which are related to +the changed route. +.Pp +In addition to the facilities described above, +.Nm routed +supports the notion of ``distant'' +.Em passive +and +.Em active +gateways. When +.Nm routed +is started up, it reads the file +.Pa /etc/gateways +to find gateways which may not be located using +only information from the +.Dv SIOGIFCONF +.Xr ioctl 2 . +Gateways specified in this manner should be marked passive +if they are not expected to exchange routing information, +while gateways marked active +should be willing to exchange routing information (i.e. +they should have a +.Nm routed +process running on the machine). +Routes through passive gateways are installed in the +kernel's routing tables once upon startup. +Such routes are not included in +any routing information transmitted. +Active gateways are treated equally to network +interfaces. Routing information is distributed +to the gateway and if no routing information is +received for a period of time, the associated +route is deleted. +Gateways marked +.Em external +are also passive, but are not placed in the kernel +routing table nor are they included in routing updates. +The function of external entries is to inform +.Nm routed +that another routing process +will install such a route, and that alternate routes to that destination +should not be installed. +Such entries are only required when both routers may learn of routes +to the same destination. +.Pp +The +.Pa /etc/gateways +is comprised of a series of lines, each in +the following format: +.Bd -ragged +.Pf < Cm net No \&| +.Cm host Ns > +.Ar name1 +.Cm gateway +.Ar name2 +.Cm metric +.Ar value +.Pf < Cm passive No \&| +.Cm active No \&| +.Cm external Ns > +.Ed +.Pp +The +.Cm net +or +.Cm host +keyword indicates if the route is to a network or specific host. +.Pp +.Ar Name1 +is the name of the destination network or host. This may be a +symbolic name located in +.Pa /etc/networks +or +.Pa /etc/hosts +(or, if started after +.Xr named 8 , +known to the name server), +or an Internet address specified in ``dot'' notation; see +.Xr inet 3 . +.Pp +.Ar Name2 +is the name or address of the gateway to which messages should +be forwarded. +.Pp +.Ar Value +is a metric indicating the hop count to the destination host +or network. +.Pp +One of the keywords +.Cm passive , +.Cm active +or +.Cm external +indicates if the gateway should be treated as +.Em passive +or +.Em active +(as described above), +or whether the gateway is +.Em external +to the scope of the +.Nm routed +protocol. +.Pp +Internetwork routers that are directly attached to the Arpanet or Milnet +should use the Exterior Gateway Protocol +.Pq Tn EGP +to gather routing information +rather then using a static routing table of passive gateways. +.Tn EGP +is required in order to provide routes for local networks to the rest +of the Internet system. +.Sh FILES +.Bl -tag -width /etc/gateways -compact +.It Pa /etc/gateways +for distant gateways +.El +.Sh SEE ALSO +.Xr udp 4 , +.Xr icmp 4 , +.Xr XNSrouted 8 , +.Xr htable 8 +.Rs +.%T Internet Transport Protocols +.%R XSIS 028112 +.%Q Xerox System Integration Standard +.Re +.Sh BUGS +The kernel's routing tables may not correspond to those of +.Nm routed +when redirects change or add routes. +.Nm Routed +should note any redirects received by reading +the +.Tn ICMP +packets received via a raw socket. +.Pp +.Nm Routed +should incorporate other routing protocols, +such as Xerox +.Tn \&NS +.Pq Xr XNSrouted 8 +and +.Tn EGP . +Using separate processes for each requires configuration options +to avoid redundant or competing routes. +.Pp +.Nm Routed +should listen to intelligent interfaces, such as an +.Tn IMP , +to gather more information. +It does not always detect unidirectional failures in network interfaces +(e.g., when the output side fails). +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/routed.tproj/startup.c b/routed.tproj/startup.c new file mode 100644 index 0000000..c183ac6 --- /dev/null +++ b/routed.tproj/startup.c @@ -0,0 +1,537 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +struct interface *ifnet; +struct interface **ifnext = &ifnet; +int lookforinterfaces = 1; +int externalinterfaces = 0; /* # of remote and local interfaces */ +int foundloopback; /* valid flag for loopaddr */ +struct sockaddr loopaddr; /* our address on loopback */ + + +void +quit(s) + char *s; +{ + extern int errno; + int sverrno = errno; + + (void) fprintf(stderr, "route: "); + if (s) + (void) fprintf(stderr, "%s: ", s); + (void) fprintf(stderr, "%s\n", strerror(sverrno)); + exit(1); + /* NOTREACHED */ +} + +struct rt_addrinfo info; +/* Sleazy use of local variables throughout file, warning!!!! */ +#define netmask info.rti_info[RTAX_NETMASK] +#define ifaaddr info.rti_info[RTAX_IFA] +#define brdaddr info.rti_info[RTAX_BRD] + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +void +rt_xaddrs(cp, cplim, rtinfo) + register caddr_t cp, cplim; + register struct rt_addrinfo *rtinfo; +{ + register struct sockaddr *sa; + register int i; + + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + +/* + * Find the network interfaces which have configured themselves. + * If the interface is present but not yet up (for example an + * ARPANET IMP), set the lookforinterfaces flag so we'll + * come back later and look again. + */ +ifinit() +{ + struct interface ifs, *ifp; + size_t needed; + int mib[6], no_ipaddr = 0, flags = 0; + char *buf, *cplim, *cp; + register struct if_msghdr *ifm; + register struct ifa_msghdr *ifam; + struct sockaddr_dl *sdl; + struct sockaddr_in *sin; + u_long i; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + quit("route-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + quit("malloc"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + quit("actual retrieval of interface table"); + lookforinterfaces = 0; + cplim = buf + needed; + for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)cp; + if (ifm->ifm_type == RTM_IFINFO) { + memset(&ifs, 0, sizeof(ifs)); + ifs.int_flags = flags = (0xffff & ifm->ifm_flags) | IFF_INTERFACE; + if ((flags & IFF_UP) == 0 || no_ipaddr) + lookforinterfaces = 1; + sdl = (struct sockaddr_dl *) (ifm + 1); + sdl->sdl_data[sdl->sdl_nlen] = 0; + no_ipaddr = 1; + continue; + } + if (ifm->ifm_type != RTM_NEWADDR) + quit("ifinit: out of sync"); + if ((flags & IFF_UP) == 0) + continue; + ifam = (struct ifa_msghdr *)ifm; + info.rti_addrs = ifam->ifam_addrs; + rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); + if (ifaaddr == 0) { + syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); + continue; + } + ifs.int_addr = *ifaaddr; + if (ifs.int_addr.sa_family != AF_INET) + continue; + no_ipaddr = 0; + if (ifs.int_flags & IFF_POINTOPOINT) { + if (brdaddr == 0) { + syslog(LOG_ERR, "%s: (get dstaddr)", + sdl->sdl_data); + continue; + } + if (brdaddr->sa_family == AF_UNSPEC) { + lookforinterfaces = 1; + continue; + } + ifs.int_dstaddr = *brdaddr; + } + /* + * already known to us? + * This allows multiple point-to-point links + * to share a source address (possibly with one + * other link), but assumes that there will not be + * multiple links with the same destination address. + */ + if (ifs.int_flags & IFF_POINTOPOINT) { + if (if_ifwithdstaddr(&ifs.int_dstaddr)) + continue; + } else if (if_ifwithaddr(&ifs.int_addr)) + continue; + if (ifs.int_flags & IFF_LOOPBACK) { + ifs.int_flags |= IFF_PASSIVE; + foundloopback = 1; + loopaddr = ifs.int_addr; + for (ifp = ifnet; ifp; ifp = ifp->int_next) + if (ifp->int_flags & IFF_POINTOPOINT) + add_ptopt_localrt(ifp); + } + if (ifs.int_flags & IFF_BROADCAST) { + if (brdaddr == 0) { + syslog(LOG_ERR, "%s: (get broadaddr)", + sdl->sdl_data); + continue; + } + ifs.int_dstaddr = *brdaddr; + } + /* + * Use a minimum metric of one; + * treat the interface metric (default 0) + * as an increment to the hop count of one. + */ + ifs.int_metric = ifam->ifam_metric + 1; + if (netmask == 0) { + syslog(LOG_ERR, "%s: (get netmask)", + sdl->sdl_data); + continue; + } + sin = (struct sockaddr_in *)netmask; + ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr); + sin = (struct sockaddr_in *)&ifs.int_addr; + i = ntohl(sin->sin_addr.s_addr); + if (IN_CLASSA(i)) + ifs.int_netmask = IN_CLASSA_NET; + else if (IN_CLASSB(i)) + ifs.int_netmask = IN_CLASSB_NET; + else + ifs.int_netmask = IN_CLASSC_NET; + ifs.int_net = i & ifs.int_netmask; + ifs.int_subnet = i & ifs.int_subnetmask; + if (ifs.int_subnetmask != ifs.int_netmask) + ifs.int_flags |= IFF_SUBNET; + ifp = (struct interface *) + malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); + if (ifp == 0) { + printf("routed: out of memory\n"); + lookforinterfaces = 1; + break; + } + *ifp = ifs; + /* + * Count the # of directly connected networks + * and point to point links which aren't looped + * back to ourself. This is used below to + * decide if we should be a routing ``supplier''. + */ + if ((ifs.int_flags & IFF_LOOPBACK) == 0 && + ((ifs.int_flags & IFF_POINTOPOINT) == 0 || + if_ifwithaddr(&ifs.int_dstaddr) == 0)) + externalinterfaces++; + /* + * If we have a point-to-point link, we want to act + * as a supplier even if it's our only interface, + * as that's the only way our peer on the other end + * can tell that the link is up. + */ + if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) + supplier = 1; + ifp->int_name = (char *)(ifp + 1); + strcpy(ifp->int_name, sdl->sdl_data); + *ifnext = ifp; + ifnext = &ifp->int_next; + traceinit(ifp); + addrouteforif(ifp); + } + if (externalinterfaces > 1 && supplier < 0) + supplier = 1; + free(buf); +} + +/* + * Add route for interface if not currently installed. + * Create route to other end if a point-to-point link, + * otherwise a route to this (sub)network. + * INTERNET SPECIFIC. + */ +addrouteforif(ifp) + register struct interface *ifp; +{ + struct sockaddr_in net; + struct sockaddr *dst; + int state; + register struct rt_entry *rt; + + if (ifp->int_flags & IFF_POINTOPOINT) + dst = &ifp->int_dstaddr; + else { + memset(&net, 0, sizeof (net)); + net.sin_family = AF_INET; + net.sin_addr = inet_makeaddr(ifp->int_subnet, INADDR_ANY); + dst = (struct sockaddr *)&net; + } + rt = rtfind(dst); + if (rt && + (rt->rt_state & (RTS_INTERFACE | RTS_INTERNAL)) == RTS_INTERFACE) + return; + if (rt) + rtdelete(rt); + /* + * If interface on subnetted network, + * install route to network as well. + * This is meant for external viewers. + */ + if ((ifp->int_flags & (IFF_SUBNET|IFF_POINTOPOINT)) == IFF_SUBNET) { + struct in_addr subnet; + + subnet = net.sin_addr; + net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); + rt = rtfind(dst); + if (rt == 0) + rtadd(dst, &ifp->int_addr, ifp->int_metric, + ((ifp->int_flags & (IFF_INTERFACE|IFF_REMOTE)) | + RTS_PASSIVE | RTS_INTERNAL | RTS_SUBNET)); + else if ((rt->rt_state & (RTS_INTERNAL|RTS_SUBNET)) == + (RTS_INTERNAL|RTS_SUBNET) && + ifp->int_metric < rt->rt_metric) + rtchange(rt, &rt->rt_router, ifp->int_metric); + net.sin_addr = subnet; + } + if (ifp->int_transitions++ > 0) + syslog(LOG_ERR, "re-installing interface %s", ifp->int_name); + state = ifp->int_flags & + (IFF_INTERFACE | IFF_PASSIVE | IFF_REMOTE | IFF_SUBNET); + if (ifp->int_flags & IFF_POINTOPOINT && + (ntohl(((struct sockaddr_in *)&ifp->int_dstaddr)->sin_addr.s_addr) & + ifp->int_netmask) != ifp->int_net) + state &= ~RTS_SUBNET; + if (ifp->int_flags & IFF_LOOPBACK) + state |= RTS_EXTERNAL; + rtadd(dst, &ifp->int_addr, ifp->int_metric, state); + if (ifp->int_flags & IFF_POINTOPOINT && foundloopback) + add_ptopt_localrt(ifp); +} + +/* + * Add route to local end of point-to-point using loopback. + * If a route to this network is being sent to neighbors on other nets, + * mark this route as subnet so we don't have to propagate it too. + */ +add_ptopt_localrt(ifp) + register struct interface *ifp; +{ + struct rt_entry *rt; + struct sockaddr *dst; + struct sockaddr_in net; + int state; + + state = RTS_INTERFACE | RTS_PASSIVE; + + /* look for route to logical network */ + memset(&net, 0, sizeof (net)); + net.sin_family = AF_INET; + net.sin_addr = inet_makeaddr(ifp->int_net, INADDR_ANY); + dst = (struct sockaddr *)&net; + rt = rtfind(dst); + if (rt && rt->rt_state & RTS_INTERNAL) + state |= RTS_SUBNET; + + dst = &ifp->int_addr; + if (rt = rtfind(dst)) { + if (rt && rt->rt_state & RTS_INTERFACE) + return; + rtdelete(rt); + } + rtadd(dst, &loopaddr, 1, state); +} + +/* + * As a concession to the ARPANET we read a list of gateways + * from /etc/gateways and add them to our tables. This file + * exists at each ARPANET gateway and indicates a set of ``remote'' + * gateways (i.e. a gateway which we can't immediately determine + * if it's present or not as we can do for those directly connected + * at the hardware level). If a gateway is marked ``passive'' + * in the file, then we assume it doesn't have a routing process + * of our design and simply assume it's always present. Those + * not marked passive are treated as if they were directly + * connected -- they're added into the interface list so we'll + * send them routing updates. + * + * PASSIVE ENTRIES AREN'T NEEDED OR USED ON GATEWAYS RUNNING EGP. + */ +gwkludge() +{ + struct sockaddr_in dst, gate; + FILE *fp; + char *type, *dname, *gname, *qual, buf[BUFSIZ]; + struct interface *ifp; + int metric, n; + struct rt_entry route; + + fp = fopen(_PATH_GATEWAYS, "r"); + if (fp == NULL) + return; + qual = buf; + dname = buf + 64; + gname = buf + ((BUFSIZ - 64) / 3); + type = buf + (((BUFSIZ - 64) * 2) / 3); + memset(&dst, 0, sizeof (dst)); + memset(&gate, 0, sizeof (gate)); + memset(&route, 0, sizeof(route)); +/* format: {net | host} XX gateway XX metric DD [passive | external]\n */ +#define readentry(fp) \ + fscanf((fp), "%s %s gateway %s metric %d %s\n", \ + type, dname, gname, &metric, qual) + for (;;) { + if ((n = readentry(fp)) == EOF) + break; + if (!getnetorhostname(type, dname, &dst)) + continue; + if (!gethostnameornumber(gname, &gate)) + continue; + if (metric == 0) /* XXX */ + metric = 1; + if (strcmp(qual, "passive") == 0) { + /* + * Passive entries aren't placed in our tables, + * only the kernel's, so we don't copy all of the + * external routing information within a net. + * Internal machines should use the default + * route to a suitable gateway (like us). + */ + route.rt_dst = *(struct sockaddr *) &dst; + route.rt_router = *(struct sockaddr *) &gate; + route.rt_flags = RTF_UP; + if (strcmp(type, "host") == 0) + route.rt_flags |= RTF_HOST; + if (metric) + route.rt_flags |= RTF_GATEWAY; + (void) rtioctl(ADD, &route.rt_rt); + continue; + } + if (strcmp(qual, "external") == 0) { + /* + * Entries marked external are handled + * by other means, e.g. EGP, + * and are placed in our tables only + * to prevent overriding them + * with something else. + */ + rtadd(&dst, &gate, metric, RTS_EXTERNAL|RTS_PASSIVE); + continue; + } + /* assume no duplicate entries */ + externalinterfaces++; + ifp = (struct interface *)malloc(sizeof (*ifp)); + memset(ifp, 0, sizeof (*ifp)); + ifp->int_flags = IFF_REMOTE; + /* can't identify broadcast capability */ + ifp->int_net = inet_netof(dst.sin_addr); + if (strcmp(type, "host") == 0) { + ifp->int_flags |= IFF_POINTOPOINT; + ifp->int_dstaddr = *((struct sockaddr *)&dst); + } + ifp->int_addr = *((struct sockaddr *)&gate); + ifp->int_metric = metric; + ifp->int_next = ifnet; + ifnet = ifp; + addrouteforif(ifp); + } + fclose(fp); +} + +getnetorhostname(type, name, sin) + char *type, *name; + struct sockaddr_in *sin; +{ + + if (strcmp(type, "net") == 0) { + struct netent *np = getnetbyname(name); + int n; + + if (np == 0) + n = inet_network(name); + else { + if (np->n_addrtype != AF_INET) + return (0); + n = np->n_net; + /* + * getnetbyname returns right-adjusted value. + */ + if (n < 128) + n <<= IN_CLASSA_NSHIFT; + else if (n < 65536) + n <<= IN_CLASSB_NSHIFT; + else + n <<= IN_CLASSC_NSHIFT; + } + sin->sin_family = AF_INET; + sin->sin_addr = inet_makeaddr(n, INADDR_ANY); + return (1); + } + if (strcmp(type, "host") == 0) { + struct hostent *hp = gethostbyname(name); + + if (hp == 0) + sin->sin_addr.s_addr = inet_addr(name); + else { + if (hp->h_addrtype != AF_INET) + return (0); + memmove(&sin->sin_addr, hp->h_addr, hp->h_length); + } + sin->sin_family = AF_INET; + return (1); + } + return (0); +} + +gethostnameornumber(name, sin) + char *name; + struct sockaddr_in *sin; +{ + struct hostent *hp; + + hp = gethostbyname(name); + if (hp) { + memmove(&sin->sin_addr, hp->h_addr, hp->h_length); + sin->sin_family = hp->h_addrtype; + return (1); + } + sin->sin_addr.s_addr = inet_addr(name); + sin->sin_family = AF_INET; + return (sin->sin_addr.s_addr != -1); +} diff --git a/routed.tproj/table.h b/routed.tproj/table.h new file mode 100644 index 0000000..3e0246d --- /dev/null +++ b/routed.tproj/table.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + +/* + * Routing table management daemon. + */ + +/* + * Routing table structure; differs a bit from kernel tables. + * + * Note: the union below must agree in the first 4 members + * so the ioctl's will work. + */ +struct rthash { + struct rt_entry *rt_forw; + struct rt_entry *rt_back; +}; +#ifdef RTM_ADD +#define rtentry ortentry +#endif + +struct rt_entry { + struct rt_entry *rt_forw; + struct rt_entry *rt_back; + union { + struct rtentry rtu_rt; + struct rtuentry { + u_long rtu_hash; + struct sockaddr rtu_dst; + struct sockaddr rtu_router; + short rtu_rtflags; /* used by rtioctl */ + short rtu_wasted[5]; + int rtu_flags; + int rtu_state; + int rtu_timer; + int rtu_metric; + int rtu_ifmetric; + struct interface *rtu_ifp; + } rtu_entry; + } rt_rtu; +}; + +#define rt_rt rt_rtu.rtu_entry /* pass to ioctl */ +#define rt_hash rt_rtu.rtu_entry.rtu_hash /* for net or host */ +#define rt_dst rt_rtu.rtu_entry.rtu_dst /* match value */ +#define rt_router rt_rtu.rtu_entry.rtu_router /* who to forward to */ +#define rt_flags rt_rtu.rtu_entry.rtu_flags /* kernel flags */ +#define rt_timer rt_rtu.rtu_entry.rtu_timer /* for invalidation */ +#define rt_state rt_rtu.rtu_entry.rtu_state /* see below */ +#define rt_metric rt_rtu.rtu_entry.rtu_metric /* cost of route */ +#define rt_ifmetric rt_rtu.rtu_entry.rtu_ifmetric /* cost of route if */ +#define rt_ifp rt_rtu.rtu_entry.rtu_ifp /* interface to take */ + +#define ROUTEHASHSIZ 32 /* must be a power of 2 */ +#define ROUTEHASHMASK (ROUTEHASHSIZ - 1) + +/* + * "State" of routing table entry. + */ +#define RTS_CHANGED 0x1 /* route has been altered recently */ +#define RTS_EXTERNAL 0x2 /* extern info, not installed or sent */ +#define RTS_INTERNAL 0x4 /* internal route, not installed */ +#define RTS_PASSIVE IFF_PASSIVE /* don't time out route */ +#define RTS_INTERFACE IFF_INTERFACE /* route is for network interface */ +#define RTS_REMOTE IFF_REMOTE /* route is for ``remote'' entity */ +#define RTS_SUBNET IFF_SUBNET /* route is for network subnet */ + +/* + * Flags are same as kernel, with this addition for af_rtflags: + */ +#define RTF_SUBNET 0x80000 /* pseudo: route to subnet */ + +EXTERN struct rthash nethash[ROUTEHASHSIZ]; +EXTERN struct rthash hosthash[ROUTEHASHSIZ]; +struct rt_entry *rtlookup(); +struct rt_entry *rtfind(); diff --git a/routed.tproj/tables.c b/routed.tproj/tables.c new file mode 100644 index 0000000..f9ade65 --- /dev/null +++ b/routed.tproj/tables.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" +#include +#include +#include + +#ifndef DEBUG +#define DEBUG 0 +#endif + +#ifdef RTM_ADD +#define FIXLEN(s) {if ((s)->sa_len == 0) (s)->sa_len = sizeof *(s);} +#else +#define FIXLEN(s) { } +#endif + +int install = !DEBUG; /* if 1 call kernel */ + +/* + * Lookup dst in the tables for an exact match. + */ +struct rt_entry * +rtlookup(dst) + struct sockaddr *dst; +{ + register struct rt_entry *rt; + register struct rthash *rh; + register u_int hash; + struct afhash h; + int doinghost = 1; + + if (dst->sa_family >= af_max) + return (0); + (*afswitch[dst->sa_family].af_hash)(dst, &h); + hash = h.afh_hosthash; + rh = &hosthash[hash & ROUTEHASHMASK]; +again: + for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { + if (rt->rt_hash != hash) + continue; + if (equal(&rt->rt_dst, dst)) + return (rt); + } + if (doinghost) { + doinghost = 0; + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; + goto again; + } + return (0); +} + +struct sockaddr wildcard; /* zero valued cookie for wildcard searches */ + +/* + * Find a route to dst as the kernel would. + */ +struct rt_entry * +rtfind(dst) + struct sockaddr *dst; +{ + register struct rt_entry *rt; + register struct rthash *rh; + register u_int hash; + struct afhash h; + int af = dst->sa_family; + int doinghost = 1, (*match)(); + + if (af >= af_max) + return (0); + (*afswitch[af].af_hash)(dst, &h); + hash = h.afh_hosthash; + rh = &hosthash[hash & ROUTEHASHMASK]; + +again: + for (rt = rh->rt_forw; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { + if (rt->rt_hash != hash) + continue; + if (doinghost) { + if (equal(&rt->rt_dst, dst)) + return (rt); + } else { + if (rt->rt_dst.sa_family == af && + (*match)(&rt->rt_dst, dst)) + return (rt); + } + } + if (doinghost) { + doinghost = 0; + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; + match = afswitch[af].af_netmatch; + goto again; + } +#ifdef notyet + /* + * Check for wildcard gateway, by convention network 0. + */ + if (dst != &wildcard) { + dst = &wildcard, hash = 0; + goto again; + } +#endif + return (0); +} + +rtadd(dst, gate, metric, state) + struct sockaddr *dst, *gate; + int metric, state; +{ + struct afhash h; + register struct rt_entry *rt; + struct rthash *rh; + int af = dst->sa_family, flags; + u_int hash; + + if (af >= af_max) + return; + (*afswitch[af].af_hash)(dst, &h); + flags = (*afswitch[af].af_rtflags)(dst); + /* + * Subnet flag isn't visible to kernel, move to state. XXX + */ + FIXLEN(dst); + FIXLEN(gate); + if (flags & RTF_SUBNET) { + state |= RTS_SUBNET; + flags &= ~RTF_SUBNET; + } + if (flags & RTF_HOST) { + hash = h.afh_hosthash; + rh = &hosthash[hash & ROUTEHASHMASK]; + } else { + hash = h.afh_nethash; + rh = &nethash[hash & ROUTEHASHMASK]; + } + rt = (struct rt_entry *)malloc(sizeof (*rt)); + if (rt == 0) + return; + rt->rt_hash = hash; + rt->rt_dst = *dst; + rt->rt_router = *gate; + rt->rt_timer = 0; + rt->rt_flags = RTF_UP | flags; + rt->rt_state = state | RTS_CHANGED; + rt->rt_ifp = if_ifwithdstaddr(&rt->rt_dst); + if (rt->rt_ifp == 0) + rt->rt_ifp = if_ifwithnet(&rt->rt_router); + if ((state & RTS_INTERFACE) == 0) + rt->rt_flags |= RTF_GATEWAY; + rt->rt_metric = metric; + insque(rt, rh); + TRACE_ACTION("ADD", rt); + /* + * If the ioctl fails because the gateway is unreachable + * from this host, discard the entry. This should only + * occur because of an incorrect entry in /etc/gateways. + */ + if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 && + rtioctl(ADD, &rt->rt_rt) < 0) { + if (errno != EEXIST && gate->sa_family < af_max) + syslog(LOG_ERR, + "adding route to net/host %s through gateway %s: %m\n", + (*afswitch[dst->sa_family].af_format)(dst), + (*afswitch[gate->sa_family].af_format)(gate)); + perror("ADD ROUTE"); + if (errno == ENETUNREACH) { + TRACE_ACTION("DELETE", rt); + remque(rt); + free((char *)rt); + } + } +} + +rtchange(rt, gate, metric) + struct rt_entry *rt; + struct sockaddr *gate; + short metric; +{ + int add = 0, delete = 0, newgateway = 0; + struct rtuentry oldroute; + + FIXLEN(gate); + FIXLEN(&(rt->rt_router)); + FIXLEN(&(rt->rt_dst)); + if (!equal(&rt->rt_router, gate)) { + newgateway++; + TRACE_ACTION("CHANGE FROM ", rt); + } else if (metric != rt->rt_metric) + TRACE_NEWMETRIC(rt, metric); + if ((rt->rt_state & RTS_INTERNAL) == 0) { + /* + * If changing to different router, we need to add + * new route and delete old one if in the kernel. + * If the router is the same, we need to delete + * the route if has become unreachable, or re-add + * it if it had been unreachable. + */ + if (newgateway) { + add++; + if (rt->rt_metric != HOPCNT_INFINITY) + delete++; + } else if (metric == HOPCNT_INFINITY) + delete++; + else if (rt->rt_metric == HOPCNT_INFINITY) + add++; + } + if (delete) + oldroute = rt->rt_rt; + if ((rt->rt_state & RTS_INTERFACE) && delete) { + rt->rt_state &= ~RTS_INTERFACE; + rt->rt_flags |= RTF_GATEWAY; + if (metric > rt->rt_metric && delete) + syslog(LOG_ERR, "%s route to interface %s (timed out)", + add? "changing" : "deleting", + rt->rt_ifp ? rt->rt_ifp->int_name : "?"); + } + if (add) { + rt->rt_router = *gate; + rt->rt_ifp = if_ifwithdstaddr(&rt->rt_router); + if (rt->rt_ifp == 0) + rt->rt_ifp = if_ifwithnet(&rt->rt_router); + } + rt->rt_metric = metric; + rt->rt_state |= RTS_CHANGED; + if (newgateway) + TRACE_ACTION("CHANGE TO ", rt); +#ifndef RTM_ADD + if (add && rtioctl(ADD, &rt->rt_rt) < 0) + perror("ADD ROUTE"); + if (delete && rtioctl(DELETE, &oldroute) < 0) + perror("DELETE ROUTE"); +#else + if (delete && !add) { + if (rtioctl(DELETE, &oldroute) < 0) + perror("DELETE ROUTE"); + } else if (!delete && add) { + if (rtioctl(ADD, &rt->rt_rt) < 0) + perror("ADD ROUTE"); + } else if (delete && add) { + if (rtioctl(CHANGE, &rt->rt_rt) < 0) + perror("CHANGE ROUTE"); + } +#endif +} + +rtdelete(rt) + struct rt_entry *rt; +{ + + TRACE_ACTION("DELETE", rt); + FIXLEN(&(rt->rt_router)); + FIXLEN(&(rt->rt_dst)); + if (rt->rt_metric < HOPCNT_INFINITY) { + if ((rt->rt_state & (RTS_INTERFACE|RTS_INTERNAL)) == RTS_INTERFACE) + syslog(LOG_ERR, + "deleting route to interface %s? (timed out?)", + rt->rt_ifp->int_name); + if ((rt->rt_state & (RTS_INTERNAL | RTS_EXTERNAL)) == 0 && + rtioctl(DELETE, &rt->rt_rt) < 0) + perror("rtdelete"); + } + remque(rt); + free((char *)rt); +} + +rtdeleteall(sig) + int sig; +{ + register struct rthash *rh; + register struct rt_entry *rt; + struct rthash *base = hosthash; + int doinghost = 1; + +again: + for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { + rt = rh->rt_forw; + for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { + if (rt->rt_state & RTS_INTERFACE || + rt->rt_metric >= HOPCNT_INFINITY) + continue; + TRACE_ACTION("DELETE", rt); + if ((rt->rt_state & (RTS_INTERNAL|RTS_EXTERNAL)) == 0 && + rtioctl(DELETE, &rt->rt_rt) < 0) + perror("rtdeleteall"); + } + } + if (doinghost) { + doinghost = 0; + base = nethash; + goto again; + } + exit(sig); +} + +/* + * If we have an interface to the wide, wide world, + * add an entry for an Internet default route (wildcard) to the internal + * tables and advertise it. This route is not added to the kernel routes, + * but this entry prevents us from listening to other people's defaults + * and installing them in the kernel here. + */ +rtdefault() +{ + extern struct sockaddr inet_default; + + rtadd(&inet_default, &inet_default, 1, + RTS_CHANGED | RTS_PASSIVE | RTS_INTERNAL); +} + +rtinit() +{ + register struct rthash *rh; + + for (rh = nethash; rh < &nethash[ROUTEHASHSIZ]; rh++) + rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; + for (rh = hosthash; rh < &hosthash[ROUTEHASHSIZ]; rh++) + rh->rt_forw = rh->rt_back = (struct rt_entry *)rh; +} + +rtioctl(action, ort) + int action; + struct rtuentry *ort; +{ +#ifndef RTM_ADD + if (install == 0) + return (errno = 0); + ort->rtu_rtflags = ort->rtu_flags; + switch (action) { + + case ADD: + return (ioctl(s, SIOCADDRT, (char *)ort)); + + case DELETE: + return (ioctl(s, SIOCDELRT, (char *)ort)); + + default: + return (-1); + } +#else /* RTM_ADD */ + struct { + struct rt_msghdr w_rtm; + struct sockaddr_in w_dst; + struct sockaddr w_gate; + struct sockaddr_in w_netmask; + } w; +#define rtm w.w_rtm + + memset(&w, 0, sizeof(w)); + rtm.rtm_msglen = sizeof(w); + rtm.rtm_version = RTM_VERSION; + rtm.rtm_type = (action == ADD ? RTM_ADD : + (action == DELETE ? RTM_DELETE : RTM_CHANGE)); +#undef rt_dst + rtm.rtm_flags = ort->rtu_flags; + rtm.rtm_seq = ++seqno; + rtm.rtm_addrs = RTA_DST|RTA_GATEWAY; + memmove(&w.w_dst, &ort->rtu_dst, sizeof(w.w_dst)); + memmove(&w.w_gate, &ort->rtu_router, sizeof(w.w_gate)); + w.w_dst.sin_family = AF_INET; + w.w_dst.sin_len = sizeof(w.w_dst); + w.w_gate.sa_family = AF_INET; + w.w_gate.sa_len = sizeof(w.w_gate); + if (rtm.rtm_flags & RTF_HOST) { + rtm.rtm_msglen -= sizeof(w.w_netmask); + } else { + register char *cp; + int len; + + rtm.rtm_addrs |= RTA_NETMASK; + w.w_netmask.sin_addr.s_addr = + inet_maskof(w.w_dst.sin_addr.s_addr); + for (cp = (char *)(1 + &w.w_netmask.sin_addr); + --cp > (char *) &w.w_netmask; ) + if (*cp) + break; + len = cp - (char *)&w.w_netmask; + if (len) { + len++; + w.w_netmask.sin_len = len; + len = 1 + ((len - 1) | (sizeof(long) - 1)); + } else + len = sizeof(long); + rtm.rtm_msglen -= (sizeof(w.w_netmask) - len); + } + errno = 0; + return (install ? write(r, (char *)&w, rtm.rtm_msglen) : (errno = 0)); +#endif /* RTM_ADD */ +} diff --git a/routed.tproj/timer.c b/routed.tproj/timer.c new file mode 100644 index 0000000..cf8e3ba --- /dev/null +++ b/routed.tproj/timer.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#include "defs.h" + +int faketime; + +/* + * Timer routine. Performs routing information supply + * duties and manages timers on routing table entries. + * Management of the RTS_CHANGED bit assumes that we broadcast + * each time called. + */ +void +timer() +{ + register struct rthash *rh; + register struct rt_entry *rt; + struct rthash *base = hosthash; + int doinghost = 1, timetobroadcast; + extern int externalinterfaces; + + (void) gettimeofday(&now, (struct timezone *)NULL); + faketime += TIMER_RATE; + if (lookforinterfaces && (faketime % CHECK_INTERVAL) == 0) + ifinit(); + timetobroadcast = supplier && (faketime % SUPPLY_INTERVAL) == 0; +again: + for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { + rt = rh->rt_forw; + for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) { + /* + * We don't advance time on a routing entry for + * a passive gateway, or any interface if we're + * not acting as supplier. + */ + if (!(rt->rt_state & RTS_PASSIVE) && + (supplier || !(rt->rt_state & RTS_INTERFACE))) + rt->rt_timer += TIMER_RATE; + if (rt->rt_timer >= GARBAGE_TIME) { + rt = rt->rt_back; + rtdelete(rt->rt_forw); + continue; + } + if (rt->rt_timer >= EXPIRE_TIME && + rt->rt_metric < HOPCNT_INFINITY) + rtchange(rt, &rt->rt_router, HOPCNT_INFINITY); + rt->rt_state &= ~RTS_CHANGED; + } + } + if (doinghost) { + doinghost = 0; + base = nethash; + goto again; + } + if (timetobroadcast) { + toall(supply, 0, (struct interface *)NULL); + lastbcast = now; + lastfullupdate = now; + needupdate = 0; /* cancel any pending dynamic update */ + nextbcast.tv_sec = 0; + } +} + +/* + * On hangup, let everyone know we're going away. + */ +hup() +{ + register struct rthash *rh; + register struct rt_entry *rt; + struct rthash *base = hosthash; + int doinghost = 1; + + if (supplier) { +again: + for (rh = base; rh < &base[ROUTEHASHSIZ]; rh++) { + rt = rh->rt_forw; + for (; rt != (struct rt_entry *)rh; rt = rt->rt_forw) + rt->rt_metric = HOPCNT_INFINITY; + } + if (doinghost) { + doinghost = 0; + base = nethash; + goto again; + } + toall(supply, 0, (struct interface *)NULL); + } + exit(1); +} diff --git a/routed.tproj/trace.c b/routed.tproj/trace.c new file mode 100644 index 0000000..8695cf9 --- /dev/null +++ b/routed.tproj/trace.c @@ -0,0 +1,448 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + + +/* + * Routing Table Management Daemon + */ +#define RIPCMDS +#include "defs.h" +#include +#include +#include +#include +#include "pathnames.h" + +#define NRECORDS 50 /* size of circular trace buffer */ +#ifdef DEBUG +FILE *ftrace = stdout; +int traceactions = 0; +#endif +static struct timeval lastlog; +static char *savetracename; + +traceinit(ifp) + register struct interface *ifp; +{ + static int iftraceinit(); + + if (iftraceinit(ifp, &ifp->int_input) && + iftraceinit(ifp, &ifp->int_output)) + return; + tracehistory = 0; + fprintf(stderr, "traceinit: can't init %s\n", ifp->int_name); +} + +static +iftraceinit(ifp, ifd) + struct interface *ifp; + register struct ifdebug *ifd; +{ + register struct iftrace *t; + + ifd->ifd_records = + (struct iftrace *)malloc(NRECORDS * sizeof (struct iftrace)); + if (ifd->ifd_records == 0) + return (0); + ifd->ifd_front = ifd->ifd_records; + ifd->ifd_count = 0; + for (t = ifd->ifd_records; t < ifd->ifd_records + NRECORDS; t++) { + t->ift_size = 0; + t->ift_packet = 0; + } + ifd->ifd_if = ifp; + return (1); +} + +traceon(file) + char *file; +{ + struct stat stbuf; + + if (ftrace != NULL) + return; + if (stat(file, &stbuf) >= 0 && (stbuf.st_mode & S_IFMT) != S_IFREG) + return; + savetracename = file; + (void) gettimeofday(&now, (struct timezone *)NULL); + ftrace = fopen(file, "a"); + if (ftrace == NULL) + return; + dup2(fileno(ftrace), 1); + dup2(fileno(ftrace), 2); + traceactions = 1; + fprintf(ftrace, "Tracing enabled %s\n", ctime((time_t *)&now.tv_sec)); +} + +traceoff() +{ + if (!traceactions) + return; + if (ftrace != NULL) { + int fd = open(_PATH_DEVNULL, O_RDWR); + + fprintf(ftrace, "Tracing disabled %s\n", + ctime((time_t *)&now.tv_sec)); + fflush(ftrace); + (void) dup2(fd, 1); + (void) dup2(fd, 2); + (void) close(fd); + fclose(ftrace); + ftrace = NULL; + } + traceactions = 0; + tracehistory = 0; + tracepackets = 0; + tracecontents = 0; +} + +void +sigtrace(s) + int s; +{ + + if (s == SIGUSR2) + traceoff(); + else if (ftrace == NULL && savetracename) + traceon(savetracename); + else + bumploglevel(); +} + +/* + * Move to next higher level of tracing when -t option processed or + * SIGUSR1 is received. Successive levels are: + * traceactions + * traceactions + tracepackets + * traceactions + tracehistory (packets and contents after change) + * traceactions + tracepackets + tracecontents + */ +bumploglevel() +{ + + (void) gettimeofday(&now, (struct timezone *)NULL); + if (traceactions == 0) { + traceactions++; + if (ftrace) + fprintf(ftrace, "Tracing actions started %s\n", + ctime((time_t *)&now.tv_sec)); + } else if (tracepackets == 0) { + tracepackets++; + tracehistory = 0; + tracecontents = 0; + if (ftrace) + fprintf(ftrace, "Tracing packets started %s\n", + ctime((time_t *)&now.tv_sec)); + } else if (tracehistory == 0) { + tracehistory++; + if (ftrace) + fprintf(ftrace, "Tracing history started %s\n", + ctime((time_t *)&now.tv_sec)); + } else { + tracepackets++; + tracecontents++; + tracehistory = 0; + if (ftrace) + fprintf(ftrace, "Tracing packet contents started %s\n", + ctime((time_t *)&now.tv_sec)); + } + if (ftrace) + fflush(ftrace); +} + +trace(ifd, who, p, len, m) + register struct ifdebug *ifd; + struct sockaddr *who; + char *p; + int len, m; +{ + register struct iftrace *t; + + if (ifd->ifd_records == 0) + return; + t = ifd->ifd_front++; + if (ifd->ifd_front >= ifd->ifd_records + NRECORDS) + ifd->ifd_front = ifd->ifd_records; + if (ifd->ifd_count < NRECORDS) + ifd->ifd_count++; + if (t->ift_size > 0 && t->ift_size < len && t->ift_packet) { + free(t->ift_packet); + t->ift_packet = 0; + } + t->ift_stamp = now; + t->ift_who = *who; + if (len > 0 && t->ift_packet == 0) { + t->ift_packet = malloc(len); + if (t->ift_packet == 0) + len = 0; + } + if (len > 0) + memmove(t->ift_packet, p, len); + t->ift_size = len; + t->ift_metric = m; +} + +traceaction(fd, action, rt) + FILE *fd; + char *action; + struct rt_entry *rt; +{ + struct sockaddr_in *dst, *gate; + static struct bits { + int t_bits; + char *t_name; + } flagbits[] = { + { RTF_UP, "UP" }, + { RTF_GATEWAY, "GATEWAY" }, + { RTF_HOST, "HOST" }, + { 0 } + }, statebits[] = { + { RTS_PASSIVE, "PASSIVE" }, + { RTS_REMOTE, "REMOTE" }, + { RTS_INTERFACE,"INTERFACE" }, + { RTS_CHANGED, "CHANGED" }, + { RTS_INTERNAL, "INTERNAL" }, + { RTS_EXTERNAL, "EXTERNAL" }, + { RTS_SUBNET, "SUBNET" }, + { 0 } + }; + register struct bits *p; + register int first; + char *cp; + struct interface *ifp; + + if (fd == NULL) + return; + if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { + fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); + lastlog = now; + } + fprintf(fd, "%s ", action); + dst = (struct sockaddr_in *)&rt->rt_dst; + gate = (struct sockaddr_in *)&rt->rt_router; + fprintf(fd, "dst %s, ", inet_ntoa(dst->sin_addr)); + fprintf(fd, "router %s, metric %d, flags", + inet_ntoa(gate->sin_addr), rt->rt_metric); + cp = " %s"; + for (first = 1, p = flagbits; p->t_bits > 0; p++) { + if ((rt->rt_flags & p->t_bits) == 0) + continue; + fprintf(fd, cp, p->t_name); + if (first) { + cp = "|%s"; + first = 0; + } + } + fprintf(fd, " state"); + cp = " %s"; + for (first = 1, p = statebits; p->t_bits > 0; p++) { + if ((rt->rt_state & p->t_bits) == 0) + continue; + fprintf(fd, cp, p->t_name); + if (first) { + cp = "|%s"; + first = 0; + } + } + fprintf(fd, " timer %d\n", rt->rt_timer); + if (tracehistory && !tracepackets && + (rt->rt_state & RTS_PASSIVE) == 0 && rt->rt_ifp) + dumpif(fd, rt->rt_ifp); + fflush(fd); + if (ferror(fd)) + traceoff(); +} + +tracenewmetric(fd, rt, newmetric) + FILE *fd; + struct rt_entry *rt; + int newmetric; +{ + struct sockaddr_in *dst, *gate; + + if (fd == NULL) + return; + if (lastlog.tv_sec != now.tv_sec || lastlog.tv_usec != now.tv_usec) { + fprintf(fd, "\n%.19s:\n", ctime((time_t *)&now.tv_sec)); + lastlog = now; + } + dst = (struct sockaddr_in *)&rt->rt_dst; + gate = (struct sockaddr_in *)&rt->rt_router; + fprintf(fd, "CHANGE metric dst %s, ", inet_ntoa(dst->sin_addr)); + fprintf(fd, "router %s, from %d to %d\n", + inet_ntoa(gate->sin_addr), rt->rt_metric, newmetric); + fflush(fd); + if (ferror(fd)) + traceoff(); +} + +dumpif(fd, ifp) + FILE *fd; + register struct interface *ifp; +{ + if (ifp->int_input.ifd_count || ifp->int_output.ifd_count) { + fprintf(fd, "*** Packet history for interface %s ***\n", + ifp->int_name); +#ifdef notneeded + dumptrace(fd, "to", &ifp->int_output); +#endif + dumptrace(fd, "from", &ifp->int_input); + fprintf(fd, "*** end packet history ***\n"); + } +} + +dumptrace(fd, dir, ifd) + FILE *fd; + char *dir; + register struct ifdebug *ifd; +{ + register struct iftrace *t; + char *cp = !strcmp(dir, "to") ? "Output" : "Input"; + + if (ifd->ifd_front == ifd->ifd_records && + ifd->ifd_front->ift_size == 0) { + fprintf(fd, "%s: no packets.\n", cp); + fflush(fd); + return; + } + fprintf(fd, "%s trace:\n", cp); + t = ifd->ifd_front - ifd->ifd_count; + if (t < ifd->ifd_records) + t += NRECORDS; + for ( ; ifd->ifd_count; ifd->ifd_count--, t++) { + if (t >= ifd->ifd_records + NRECORDS) + t = ifd->ifd_records; + if (t->ift_size == 0) + continue; + dumppacket(fd, dir, &t->ift_who, t->ift_packet, t->ift_size, + &t->ift_stamp); + } +} + +dumppacket(fd, dir, who, cp, size, stamp) + FILE *fd; + struct sockaddr_in *who; /* should be sockaddr */ + char *dir, *cp; + register int size; + struct timeval *stamp; +{ + register struct rip *msg = (struct rip *)cp; + register struct netinfo *n; + + if (fd == NULL) + return; + if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX) + fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd], + dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port), + ctime((time_t *)&stamp->tv_sec)); + else { + fprintf(fd, "Bad cmd 0x%x %s %x.%d %.19s\n", msg->rip_cmd, + dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port)); + fprintf(fd, "size=%d cp=%x packet=%x\n", size, cp, packet, + ctime((time_t *)&stamp->tv_sec)); + fflush(fd); + return; + } + if (tracepackets && tracecontents == 0) { + fflush(fd); + return; + } + switch (msg->rip_cmd) { + + case RIPCMD_REQUEST: + case RIPCMD_RESPONSE: + size -= 4 * sizeof (char); + n = msg->rip_nets; + for (; size > 0; n++, size -= sizeof (struct netinfo)) { + if (size < sizeof (struct netinfo)) { + fprintf(fd, "(truncated record, len %d)\n", + size); + break; + } + if (sizeof(n->rip_dst.sa_family) > 1) + n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family); + + switch ((int)n->rip_dst.sa_family) { + + case AF_INET: + fprintf(fd, "\tdst %s metric %d\n", +#define satosin(sa) ((struct sockaddr_in *)&sa) + inet_ntoa(satosin(n->rip_dst)->sin_addr), + ntohl(n->rip_metric)); + break; + + default: + fprintf(fd, "\taf %d? metric %d\n", + n->rip_dst.sa_family, + ntohl(n->rip_metric)); + break; + } + } + break; + + case RIPCMD_TRACEON: + fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile); + break; + + case RIPCMD_TRACEOFF: + break; + } + fflush(fd); + if (ferror(fd)) + traceoff(); +} diff --git a/routed.tproj/trace.h b/routed.tproj/trace.h new file mode 100644 index 0000000..aa7f753 --- /dev/null +++ b/routed.tproj/trace.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/5/93 + */ + +/* + * Routing table management daemon. + */ + +/* + * Trace record format. + */ +struct iftrace { + struct timeval ift_stamp; /* time stamp */ + struct sockaddr ift_who; /* from/to */ + char *ift_packet; /* pointer to packet */ + short ift_size; /* size of packet */ + short ift_metric; /* metric on associated metric */ +}; + +/* + * Per interface packet tracing buffers. An incoming and + * outgoing circular buffer of packets is maintained, per + * interface, for debugging. Buffers are dumped whenever + * an interface is marked down. + */ +struct ifdebug { + struct iftrace *ifd_records; /* array of trace records */ + struct iftrace *ifd_front; /* next empty trace record */ + int ifd_count; /* number of unprinted records */ + struct interface *ifd_if; /* for locating stuff */ +}; + +/* + * Packet tracing stuff. + */ +EXTERN int tracepackets; /* watch packets as they go by */ +EXTERN int tracecontents; /* watch packet contents as they go by */ +EXTERN int traceactions; /* on/off */ +EXTERN int tracehistory; /* on/off */ +EXTERN FILE *ftrace; /* output trace file */ + +#define TRACE_ACTION(action, route) { \ + if (traceactions) \ + traceaction(ftrace, action, route); \ + } +#define TRACE_NEWMETRIC(route, newmetric) { \ + if (traceactions) \ + tracenewmetric(ftrace, route, newmetric); \ + } +#define TRACE_INPUT(ifp, src, pack, size) { \ + if (tracehistory) { \ + ifp = if_iflookup(src); \ + if (ifp) \ + trace(&ifp->int_input, src, pack, size, \ + ntohl(ifp->int_metric)); \ + } \ + if (tracepackets) \ + dumppacket(ftrace, "from", src, pack, size, &now); \ + } +#define TRACE_OUTPUT(ifp, dst, size) { \ + if (tracehistory && ifp) \ + trace(&ifp->int_output, dst, packet, size, ifp->int_metric); \ + if (tracepackets) \ + dumppacket(ftrace, "to", dst, packet, size, &now); \ + } diff --git a/rpc_yppasswdd.tproj/Makefile b/rpc_yppasswdd.tproj/Makefile new file mode 100644 index 0000000..9c1a49e --- /dev/null +++ b/rpc_yppasswdd.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rpc.yppasswdd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = yppasswd.h + +CFILES = passwd.c rpc.yppasswdd.c yppasswdd_mkpw.c yppasswdd_proc.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ + rpc.yppasswdd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rpc_yppasswdd.tproj/Makefile.postamble b/rpc_yppasswdd.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/rpc_yppasswdd.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/rpc_yppasswdd.tproj/Makefile.preamble b/rpc_yppasswdd.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/rpc_yppasswdd.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/rpc_yppasswdd.tproj/PB.project b/rpc_yppasswdd.tproj/PB.project new file mode 100644 index 0000000..4e3a617 --- /dev/null +++ b/rpc_yppasswdd.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (yppasswd.h); + OTHER_LIBS = (); + OTHER_LINKED = (passwd.c, rpc.yppasswdd.c, yppasswdd_mkpw.c, yppasswdd_proc.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rpc.yppasswdd.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rpc.yppasswdd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rpc_yppasswdd.tproj/passwd.c b/rpc_yppasswdd.tproj/passwd.c new file mode 100644 index 0000000..a5d9982 --- /dev/null +++ b/rpc_yppasswdd.tproj/passwd.c @@ -0,0 +1,461 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $ */ + +/* + * Copyright (c) 1987, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +__RCSID("$NetBSD: passwd.c,v 1.11 1997/12/31 05:47:15 thorpej Exp $"); +#endif /* LIBC_SCCS and not lint */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void pw_cont __P((int sig)); +static int pw_equal __P((char *buf, struct passwd *old_pw)); + +int +pw_lock(retries) + int retries; +{ + int i, fd; + mode_t old_mode; + + /* Acquire the lock file. */ + old_mode = umask(0); + fd = open(_PATH_MASTERPASSWD_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0600); + for (i = 0; i < retries && fd < 0 && errno == EEXIST; i++) { + sleep(1); + fd = open(_PATH_MASTERPASSWD_LOCK, O_WRONLY|O_CREAT|O_EXCL, + 0600); + } + umask(old_mode); + return(fd); +} + +int +pw_mkdb() +{ + int pstat; + pid_t pid; + struct stat sb; + + /* A zero length passwd file is never ok */ + if (stat(_PATH_MASTERPASSWD_LOCK, &sb) == 0) { + if (sb.st_size == 0) { + warnx("%s is zero length", _PATH_MASTERPASSWD_LOCK); + return (-1); + } + } + + pid = vfork(); + if (pid == 0) { + execl(_PATH_PWD_MKDB, "pwd_mkdb", "-p", + _PATH_MASTERPASSWD_LOCK, NULL); + _exit(1); + } + pid = waitpid(pid, &pstat, 0); + if (pid == -1 || !WIFEXITED(pstat) || WEXITSTATUS(pstat) != 0) + return(-1); + return(0); +} + +int +pw_abort() +{ + return(unlink(_PATH_MASTERPASSWD_LOCK)); +} + +/* Everything below this point is intended for the convenience of programs + * which allow a user to interactively edit the passwd file. Errors in the + * routines below will cause the process to abort. */ + +static pid_t editpid = -1; + +static void +pw_cont(sig) + int sig; +{ + + if (editpid != -1) + kill(editpid, sig); +} + +void +pw_init() +{ + struct rlimit rlim; + + /* Unlimited resource limits. */ + rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; + (void)setrlimit(RLIMIT_CPU, &rlim); + (void)setrlimit(RLIMIT_FSIZE, &rlim); + (void)setrlimit(RLIMIT_STACK, &rlim); + (void)setrlimit(RLIMIT_DATA, &rlim); + (void)setrlimit(RLIMIT_RSS, &rlim); + + /* Don't drop core (not really necessary, but GP's). */ + rlim.rlim_cur = rlim.rlim_max = 0; + (void)setrlimit(RLIMIT_CORE, &rlim); + + /* Turn off signals. */ + (void)signal(SIGALRM, SIG_IGN); + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGPIPE, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + (void)signal(SIGTERM, SIG_IGN); + (void)signal(SIGCONT, pw_cont); +} + +void +pw_edit(notsetuid, filename) + int notsetuid; + const char *filename; +{ + int i, xargc, pstat; + char *p, *editor; + char **xargv; +#ifdef __GNUC__ + (void) &editor; +#endif + + if (filename == NULL) + filename = _PATH_MASTERPASSWD_LOCK; + if ((editor = getenv("EDITOR")) == NULL) + editor = strdup(_PATH_VI); + else + editor = strdup(editor); + if ((p = strrchr(editor, '/'))) + ++p; + else + p = editor; + + /* Scan editor string, count spaces, allocate arg vector. */ + for (i = 0, xargc = 0; p[i] != '\0'; i++) { + if (isspace(p[i])) { + while (isspace(p[i++])) + /* skip white space */ ; + if (p[i] == '\0') + break; + xargc++; + } + } + + /* argv[0] + + filename + NULL */ + xargv = (char **)malloc(sizeof(char *) * (xargc + 3)); + if (xargv == NULL) + pw_error("malloc failed", 1, 1); + + i = 0; + xargv[i++] = p; + for (; *p != '\0'; p++) { + if (isspace(*p)) { + while(isspace(*p)) + *p++ = '\0'; /* blast whitespace */ + if (*p == '\0') + break; + xargv[i++] = p; + } + } + + xargv[i++] = (char *)filename; + xargv[i] = NULL; + + if (!(editpid = vfork())) { + if (notsetuid) { + setgid(getgid()); + setuid(getuid()); + } + execvp(editor, xargv); + _exit(1); + } + for (;;) { + editpid = waitpid(editpid, (int *)&pstat, WUNTRACED); + if (editpid == -1) + pw_error(editor, 1, 1); + else if (WIFSTOPPED(pstat)) + raise(WSTOPSIG(pstat)); + else if (WIFEXITED(pstat) && WEXITSTATUS(pstat) == 0) + break; + else + pw_error(editor, 1, 1); + } + editpid = -1; + free(editor); + free(xargv); +} + +void +pw_prompt() +{ + int c; + + (void)printf("re-edit the password file? [y]: "); + (void)fflush(stdout); + c = getchar(); + if (c != EOF && c != '\n') + while (getchar() != '\n'); + if (c == 'n') + pw_error(NULL, 0, 0); +} + +/* for use in pw_copy(). Compare a pw entry to a pw struct. */ +static int +pw_equal (buf, pw) + char *buf; + struct passwd *pw; +{ + struct passwd buf_pw; + int len = strlen (buf); + if (buf[len-1] == '\n') + buf[len-1] = '\0'; + if (!pw_scan(buf, &buf_pw, NULL)) + return 0; + return !strcmp(pw->pw_name, buf_pw.pw_name) + && pw->pw_uid == buf_pw.pw_uid + && pw->pw_gid == buf_pw.pw_gid + && !strcmp(pw->pw_class, buf_pw.pw_class) + && (long)pw->pw_change == (long)buf_pw.pw_change + && (long)pw->pw_expire == (long)buf_pw.pw_expire + && !strcmp(pw->pw_gecos, buf_pw.pw_gecos) + && !strcmp(pw->pw_dir, buf_pw.pw_dir) + && !strcmp(pw->pw_shell, buf_pw.pw_shell); +} + +void +pw_copy(ffd, tfd, pw, old_pw) + int ffd, tfd; + struct passwd *pw, *old_pw; +{ + FILE *from, *to; + int done; + char *p, buf[8192]; + + if (!(from = fdopen(ffd, "r"))) + pw_error(_PATH_MASTERPASSWD, 1, 1); + if (!(to = fdopen(tfd, "w"))) + pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1); + + for (done = 0; fgets(buf, sizeof(buf), from);) { + if (!strchr(buf, '\n')) { + warnx("%s: line too long", _PATH_MASTERPASSWD); + pw_error(NULL, 0, 1); + } + if (done) { + (void)fprintf(to, "%s", buf); + if (ferror(to)) + goto err; + continue; + } + if (buf[0] == '#') { + /* skip comments for Rhapsody. */ + continue; + } + if (!(p = strchr(buf, ':'))) { + warnx("%s: corrupted entry", _PATH_MASTERPASSWD); + pw_error(NULL, 0, 1); + } + *p = '\0'; + if (strcmp(buf, pw->pw_name)) { + *p = ':'; + (void)fprintf(to, "%s", buf); + if (ferror(to)) + goto err; + continue; + } + *p = ':'; + if (old_pw && !pw_equal(buf, old_pw)) { + warnx("%s: entry inconsistent", + _PATH_MASTERPASSWD); + pw_error(NULL, 0, 1); + } + (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, + pw->pw_class, (long)pw->pw_change, (long)pw->pw_expire, + pw->pw_gecos, pw->pw_dir, pw->pw_shell); + done = 1; + if (ferror(to)) + goto err; + } + /* Only append a new entry if real uid is root! */ + if (!done) + if (getuid() == 0) + (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, + pw->pw_class, (long)pw->pw_change, + (long)pw->pw_expire, pw->pw_gecos, pw->pw_dir, + pw->pw_shell); + else + warnx("%s: changes not made, no such entry", + _PATH_MASTERPASSWD); + + if (ferror(to)) +err: pw_error(NULL, 1, 1); + (void)fclose(to); +} + +int +pw_scan(bp, pw, flags) + char *bp; + struct passwd *pw; + int *flags; +{ + unsigned long id; + int root; + char *p, *sh, *ep; + + if (flags != (int *)NULL) + *flags = 0; + + if (!(pw->pw_name = strsep(&bp, ":"))) /* login */ + goto fmt; + root = !strcmp(pw->pw_name, "root"); + + if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */ + goto fmt; + + if (!(p = strsep(&bp, ":"))) /* uid */ + goto fmt; + id = strtoul(p, &ep, 10); + if (root && id) { + warnx("root uid should be 0"); + return (0); + } + if (id > UID_MAX || *ep != '\0') { + warnx("invalid uid '%s'", p); + return (0); + } + pw->pw_uid = (uid_t)id; + if ((*p == '\0') && (flags != (int *)NULL)) + *flags |= _PASSWORD_NOUID; + + if (!(p = strsep(&bp, ":"))) /* gid */ + goto fmt; + id = strtoul(p, &ep, 10); + if (id > GID_MAX || *ep != '\0') { + warnx("invalid gid '%s'", p); + return (0); + } + pw->pw_gid = (gid_t)id; + if ((*p == '\0') && (flags != (int *)NULL)) + *flags |= _PASSWORD_NOGID; + + pw->pw_class = strsep(&bp, ":"); /* class */ + if (!(p = strsep(&bp, ":"))) /* change */ + goto fmt; + pw->pw_change = atol(p); + if ((*p == '\0') && (flags != (int *)NULL)) + *flags |= _PASSWORD_NOCHG; + if (!(p = strsep(&bp, ":"))) /* expire */ + goto fmt; + pw->pw_expire = atol(p); + if ((*p == '\0') && (flags != (int *)NULL)) + *flags |= _PASSWORD_NOEXP; + pw->pw_gecos = strsep(&bp, ":"); /* gecos */ + pw->pw_dir = strsep(&bp, ":"); /* directory */ + if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */ + goto fmt; + + p = pw->pw_shell; + if (root && *p) /* empty == /bin/sh */ + for (setusershell();;) { + if (!(sh = getusershell())) { + warnx("warning, unknown root shell"); + break; + } + if (!strcmp(p, sh)) + break; + } + + if ((p = strsep(&bp, ":"))) { /* too many */ +fmt: warnx("corrupted entry"); + return (0); + } + + return (1); +} + +void +pw_error(name, err, eval) + const char *name; + int err, eval; +{ + if (err) + warn(name); + + warnx("%s: unchanged", _PATH_MASTERPASSWD); + pw_abort(); + exit(eval); +} + diff --git a/rpc_yppasswdd.tproj/rpc.yppasswdd.8 b/rpc_yppasswdd.tproj/rpc.yppasswdd.8 new file mode 100644 index 0000000..8cda3b5 --- /dev/null +++ b/rpc_yppasswdd.tproj/rpc.yppasswdd.8 @@ -0,0 +1,97 @@ +.\" $OpenBSD: rpc.yppasswdd.8,v 1.7 1997/08/19 07:00:50 niklas Exp $ +.\" +.\" Copyright (c) 1994 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" +.Dd July 3, 1994 +.Dt RPC.YPPASSWDD 8 +.Os +.Sh NAME +.Nm rpc.yppasswdd +.Nd YP update password file daemon +.Sh SYNOPSIS +.Nm rpc.yppasswdd +.Op Fl d Ar directory +.Op Fl noshell +.Op Fl nogecos +.Op Fl nopw +.Op Fl m Ar arg1 arg2 ... +.Sh DESCRIPTION +.Nm rpc.yppasswdd +must be running on the YP master server to allow users to change information +in the password file. If the user needs to change his password this is +normally done with a program called +.Nm yppasswd . +This program doesn't exist in OpenBSD but is integrated into +.Xr passwd 1 . +.Nm passwd +will automatically determine which password database should +be modified. +To force a change of a YP password when a local one also exists, use +.Nm passwd -y . +.Pp +Other user information can be changed with +.Xr chpass 1 . +.Pp +If the file +.Nm /var/yp/yppasswdd.log +exists then messages will be written to the file. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar directory +Use the specified directory to get at the password-related files instead +of /etc. +.It Fl noshell +Don't allow changes of the shell field in the passwd file. +.It Fl nogecos +Don't allow changes of the gecos field in the passwd file. +.It Fl nopw +Don't allow changes of the password in the passwd file. +.It Fl m Ar arg1 arg2 ... +Don't use +.Ar /var/yp/securenet . +Use another file with another file format. For futher information see +man page for +.Ar ypserv.acl . +.El +.Sh FILES +.Bl -tag -width /var/yp/yppasswdd.log -compact +.It Pa /var/yp/yppasswdd.log +.It Pa /etc/passwd +.It Pa /etc/master.passwd +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr ypserv.acl 5 , +.Xr securenet 5 , +.Xr ypbind 1 +.Sh AUTHOR +Mats O Jansson diff --git a/rpc_yppasswdd.tproj/rpc.yppasswdd.c b/rpc_yppasswdd.tproj/rpc.yppasswdd.c new file mode 100644 index 0000000..1a88517 --- /dev/null +++ b/rpc_yppasswdd.tproj/rpc.yppasswdd.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: rpc.yppasswdd.c,v 1.9 1997/08/19 07:00:51 niklas Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: rpc.yppasswdd.c,v 1.9 1997/08/19 07:00:51 niklas Exp $"; +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "yppasswd.h" + +static void yppasswddprog_1(); +void sig_child(); + +int noshell, nogecos, nopw, domake; +char make_arg[1024] = "make"; +char *progname = "yppasswdd"; +char *tempname; +int debug = 0; + +void +usage() +{ + fprintf(stderr, "%s%s", + "usage: rpc.yppasswdd ", + "[-d] [-noshell] [-nogecos] [-nopw] [-m arg1 arg2 ... ]\n"); + exit(1); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + SVCXPRT *transp; + int i = 1; + + while (i < argc) { + if (argv[i][0] == '-') { + if (strcmp("-noshell", argv[i]) == 0) { + noshell = 1; + } else if (strcmp("-nogecos", argv[i]) == 0) { + nogecos = 1; + } else if (strcmp("-nopw", argv[i]) == 0) { + nopw = 1; + } else if (strcmp("-m", argv[i]) == 0) { + domake = 1; + while (i < argc) { + strcat(make_arg, " "); + strcat(make_arg, argv[i]); + i++; + } + } else if (strcmp("-d", argv[i]) == 0) { + debug = 1; + } else + usage(); + i++; + } else + usage(); + } + + if (debug == 0) { + (void) daemon(0, 0); + } + chdir("/etc"); + +/* + freopen("/dev/null", "r", stdin); + freopen("/var/yp/stderr", "w", stderr); + freopen("/var/yp/stdout", "w", stdout); +*/ + (void) pmap_unset(YPPASSWDPROG, YPPASSWDVERS); + + (void) signal(SIGCHLD, sig_child); + + transp = svcudp_create(RPC_ANYSOCK); + if (transp == NULL) { + (void) fprintf(stderr, "cannot create udp service.\n"); + exit(1); + } + if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswddprog_1, + IPPROTO_UDP)) { + fprintf(stderr, "unable to register YPPASSWDPROG, YPPASSWDVERS, udp\n"); + exit(1); + } + transp = svctcp_create(RPC_ANYSOCK, 0, 0); + if (transp == NULL) { + (void) fprintf(stderr, "cannot create tcp service.\n"); + exit(1); + } + if (!svc_register(transp, YPPASSWDPROG, YPPASSWDVERS, yppasswddprog_1, + IPPROTO_TCP)) { + fprintf(stderr, "unable to register YPPASSWDPROG, YPPASSWDVERS, tcp\n"); + exit(1); + } + svc_run(); + (void) fprintf(stderr, "svc_run returned\n"); + exit(1); +} + +static void +yppasswddprog_1(rqstp, transp) + struct svc_req *rqstp; + SVCXPRT *transp; +{ + union { + yppasswd yppasswdproc_update_1_arg; + } argument; + char *result; + bool_t(*xdr_argument) (), (*xdr_result) (); + char *(*local) (); + + switch (rqstp->rq_proc) { + case NULLPROC: + (void) svc_sendreply(transp, xdr_void, (char *) NULL); + return; + case YPPASSWDPROC_UPDATE: + xdr_argument = xdr_yppasswd; + xdr_result = xdr_int; + local = (char *(*) ()) yppasswdproc_update_1_svc; + break; + default: + svcerr_noproc(transp); + return; + } + bzero((char *) &argument, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, (caddr_t) & argument)) { + svcerr_decode(transp); + return; + } + result = (*local) (&argument, rqstp, transp); +} + +void +sig_child() +{ + int save_errno = errno; + + while (wait3((int *) NULL, WNOHANG, (struct rusage *) NULL) > 0) + ; + errno = save_errno; +} diff --git a/rpc_yppasswdd.tproj/yppasswd.h b/rpc_yppasswdd.tproj/yppasswd.h new file mode 100644 index 0000000..5592e87 --- /dev/null +++ b/rpc_yppasswdd.tproj/yppasswd.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppasswd.h,v 1.4 1997/08/19 07:00:51 niklas Exp $*/ + +/* + * Copyright (c) 1995 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef _YPPASSWD_H_RPCGEN +#define _YPPASSWD_H_RPCGEN + +struct x_passwd { + char *pw_name; + char *pw_passwd; + int pw_uid; + int pw_gid; + char *pw_gecos; + char *pw_dir; + char *pw_shell; +}; +typedef struct x_passwd x_passwd; +#ifdef __cplusplus +extern "C" bool_t xdr_x_passwd(XDR *, x_passwd*); +#elif defined(__STDC__) +extern bool_t xdr_x_passwd(XDR *, x_passwd*); +#else /* Old Style C */ +bool_t xdr_x_passwd(); +#endif /* Old Style C */ + + +struct yppasswd { + char *oldpass; + x_passwd newpw; +}; +typedef struct yppasswd yppasswd; +#ifdef __cplusplus +extern "C" bool_t xdr_yppasswd(XDR *, yppasswd*); +#elif defined(__STDC__) +extern bool_t xdr_yppasswd(XDR *, yppasswd*); +#else /* Old Style C */ +bool_t xdr_yppasswd(); +#endif /* Old Style C */ + + +#define YPPASSWDPROG ((u_long)100009) +#define YPPASSWDVERS ((u_long)1) + +#ifdef __cplusplus +#define YPPASSWDPROC_UPDATE ((u_long)1) +extern "C" int * yppasswdproc_update_1(yppasswd *, CLIENT *); +extern "C" int * yppasswdproc_update_1_svc(yppasswd *, struct svc_req *, SVCXPRT *); + +#elif defined(__STDC__) +#define YPPASSWDPROC_UPDATE ((u_long)1) +extern int * yppasswdproc_update_1(yppasswd *, CLIENT *); +extern int * yppasswdproc_update_1_svc(yppasswd *, struct svc_req *, SVCXPRT *); + +#else /* Old Style C */ +#define YPPASSWDPROC_UPDATE ((u_long)1) +extern int * yppasswdproc_update_1(); +extern int * yppasswdproc_update_1_svc(); +#endif /* Old Style C */ + +#endif /* !_YPPASSWD_H_RPCGEN */ diff --git a/rpc_yppasswdd.tproj/yppasswdd_mkpw.c b/rpc_yppasswdd.tproj/yppasswdd_mkpw.c new file mode 100644 index 0000000..6904c44 --- /dev/null +++ b/rpc_yppasswdd.tproj/yppasswdd_mkpw.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppasswdd_mkpw.c,v 1.16 1997/11/17 23:56:20 gene Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: yppasswdd_mkpw.c,v 1.16 1997/11/17 23:56:20 gene Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int noshell; +extern int nogecos; +extern int nopw; +extern int make; +extern char make_arg[]; + +static void _pw_copy(int, int, struct passwd *); + +/* This is imported from OpenBSD's libutil because it's argument + * incompatible with NetBSD's. However, the NetBSD libutil is + * at least what the prototypes suggest is in System.framework, + * even though I can't find the code. I assume it will be there + * eventually. We need to use NetBSD's because it works with the + * pwd_mkdb binary that's shipped with Rhapsody. This is an area + * where OpenBSD diverges; however, we wanted to keep the OpenBSD + * rpc.yppasswdd because the rest of our YP code is from OpenBSD. + * What a mess. + */ +static void +_pw_copy(ffd, tfd, pw) + int ffd, tfd; + struct passwd *pw; +{ + FILE *from, *to; + int done; + char *p, buf[8192]; + + if (!(from = fdopen(ffd, "r"))) + pw_error(_PATH_MASTERPASSWD, 1, 1); + if (!(to = fdopen(tfd, "w"))) + pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1); + + for (done = 0; fgets(buf, sizeof(buf), from);) { + if (!strchr(buf, '\n')) { + warnx("%s: line too long", _PATH_MASTERPASSWD); + pw_error(NULL, 0, 1); + } + if (done) { + (void)fprintf(to, "%s", buf); + if (ferror(to)) + goto err; + continue; + } + if (!(p = strchr(buf, ':'))) { + warnx("%s: corrupted entry", _PATH_MASTERPASSWD); + pw_error(NULL, 0, 1); + } + *p = '\0'; + if (strcmp(buf, pw->pw_name)) { + *p = ':'; + (void)fprintf(to, "%s", buf); + if (ferror(to)) + goto err; + continue; + } + (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, + pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, + pw->pw_dir, pw->pw_shell); + done = 1; + if (ferror(to)) + goto err; + } + if (!done) + (void)fprintf(to, "%s:%s:%d:%d:%s:%ld:%ld:%s:%s:%s\n", + pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, + pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, + pw->pw_dir, pw->pw_shell); + + if (ferror(to)) +err: + pw_error(NULL, 0, 1); + (void)fclose(to); +} + + +int +badchars(base) + char *base; +{ + int ampr = 0; + char *s; + + for (s = base; *s; s++) { + if (*s == '&') + ampr++; + if (!isprint(*s)) + return 1; + if (strchr(":\n\t\r", *s)) + return 1; + } + if (ampr > 10) + return 1; + return 0; +} + +int +subst(s, from, to) + char *s; + char from, to; +{ + int n = 0; + + while (*s) { + if (*s == from) { + *s = to; + n++; + } + s++; + } + return (n); +} + +int +make_passwd(argp) + yppasswd *argp; +{ + struct passwd pw; + int pfd, tfd; + char buf[10], *bp = NULL, *p, *t; + int n; + ssize_t cnt; + size_t resid; + struct stat st; + + pw_init(); + pfd = open(_PATH_MASTERPASSWD, O_RDONLY); + if (pfd < 0) + goto fail; + if (fstat(pfd, &st)) + goto fail; + p = bp = malloc((resid = st.st_size) + 1); + do { + cnt = read(pfd, p, resid); + if (cnt < 0) + goto fail; + p += cnt; + resid -= cnt; + } while (resid > 0); + close(pfd); + pfd = -1; + *p = '\0'; /* Buf oflow prevention */ + + p = bp; + subst(p, '\n', '\0'); + for (n = 1; p < bp + st.st_size; n++, p = t) { + t = strchr(p, '\0') + 1; + /* Rhapsody allows the passwd file to have comments in it. */ + if (p[0] == '#') { + continue; + } + cnt = subst(p, ':', '\0'); + if (cnt != 9) { + syslog(LOG_WARNING, "bad entry at line %d of %s", n, + _PATH_MASTERPASSWD); + continue; + } + + if (strcmp(p, argp->newpw.pw_name) == 0) + break; + } + if (p >= bp + st.st_size) + goto fail; + +#define EXPAND(e) e = p; while (*p++); + EXPAND(pw.pw_name); + EXPAND(pw.pw_passwd); + pw.pw_uid = atoi(p); EXPAND(t); + pw.pw_gid = atoi(p); EXPAND(t); + EXPAND(pw.pw_class); + pw.pw_change = (time_t)atol(p); EXPAND(t); + pw.pw_expire = (time_t)atol(p); EXPAND(t); + EXPAND(pw.pw_gecos); + EXPAND(pw.pw_dir); + EXPAND(pw.pw_shell); + + /* crypt() is broken under Rhapsody. It doesn't deal with + * empty keys or salts like other Unices. + */ + if (pw.pw_passwd[0] != '\0' && argp->oldpass != NULL && argp->oldpass[0] != '\0') { + if (strcmp(crypt(argp->oldpass, pw.pw_passwd), pw.pw_passwd) != 0) + goto fail; + } + + if (!nopw && badchars(argp->newpw.pw_passwd)) + goto fail; + if (!nogecos && badchars(argp->newpw.pw_gecos)) + goto fail; + if (!nogecos && badchars(argp->newpw.pw_shell)) + goto fail; + + /* + * Get the new password. Reset passwd change time to zero; when + * classes are implemented, go and get the "offset" value for this + * class and reset the timer. + */ + if (!nopw) { + pw.pw_passwd = argp->newpw.pw_passwd; + pw.pw_change = 0; + } + if (!nogecos) + pw.pw_gecos = argp->newpw.pw_gecos; + if (!noshell) + pw.pw_shell = argp->newpw.pw_shell; + + for (n = 0, p = pw.pw_gecos; *p; p++) + if (*p == '&') + n = n + strlen(pw.pw_name) - 1; + if (strlen(pw.pw_name) + 1 + strlen(pw.pw_passwd) + 1 + + strlen((sprintf(buf, "%d", pw.pw_uid), buf)) + 1 + + strlen((sprintf(buf, "%d", pw.pw_gid), buf)) + 1 + + strlen(pw.pw_gecos) + n + 1 + strlen(pw.pw_dir) + 1 + + strlen(pw.pw_shell) >= 1023) + goto fail; + + pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); + if (pfd < 0) { + syslog(LOG_ERR, "cannot open %s", _PATH_MASTERPASSWD); + goto fail; + } + + tfd = pw_lock(0); + if (tfd < 0) + goto fail; + + _pw_copy(pfd, tfd, &pw); + pw_mkdb(); + free(bp); + + if (fork() == 0) { + chdir("/var/yp"); + (void)umask(022); + system(make_arg); + exit(0); + } + return (0); + +fail: + if (bp) + free(bp); + if (pfd >= 0) + close(pfd); + return (1); +} diff --git a/rpc_yppasswdd.tproj/yppasswdd_proc.c b/rpc_yppasswdd.tproj/yppasswdd_proc.c new file mode 100644 index 0000000..2053263 --- /dev/null +++ b/rpc_yppasswdd.tproj/yppasswdd_proc.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppasswdd_proc.c,v 1.5 1997/08/19 07:00:52 niklas Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: yppasswdd_proc.c,v 1.5 1997/08/19 07:00:52 niklas Exp $"; +#endif + +#include +#include +#include +#include + +#include "yppasswd.h" + +int make_passwd __P((yppasswd *)); + +int * +yppasswdproc_update_1_svc(argp, rqstp, transp) + yppasswd *argp; + struct svc_req *rqstp; + SVCXPRT *transp; +{ + static int res; + + bzero((char *)&res, sizeof(res)); + res = make_passwd(argp); + + if (!svc_sendreply(transp, xdr_int, (char *)&res)) + svcerr_systemerr(transp); + + if (!svc_freeargs(transp, xdr_yppasswd, (caddr_t) argp)) { + (void)fprintf(stderr, "unable to free arguments\n"); + exit(1); + } + return ((void *)&res); +} diff --git a/rpcinfo.tproj/Makefile b/rpcinfo.tproj/Makefile new file mode 100644 index 0000000..808dfe4 --- /dev/null +++ b/rpcinfo.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rpcinfo + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = rpcinfo.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ + h.template + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rpcinfo.tproj/Makefile.postamble b/rpcinfo.tproj/Makefile.postamble new file mode 100644 index 0000000..7ede358 --- /dev/null +++ b/rpcinfo.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/rpcinfo.tproj/Makefile.preamble b/rpcinfo.tproj/Makefile.preamble new file mode 100644 index 0000000..30aa1b5 --- /dev/null +++ b/rpcinfo.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +INSTALLDIR = /usr/sbin diff --git a/rpcinfo.tproj/PB.project b/rpcinfo.tproj/PB.project new file mode 100644 index 0000000..00a575f --- /dev/null +++ b/rpcinfo.tproj/PB.project @@ -0,0 +1,45 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + LIBRARYSEARCH = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rpcinfo.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_MAINNIB = rpcinfo; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_MAINNIB = rpcinfo; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rpcinfo; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_MAINNIB = rpcinfo; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rpcinfo.tproj/h.template b/rpcinfo.tproj/h.template new file mode 100644 index 0000000..5dcbc5d --- /dev/null +++ b/rpcinfo.tproj/h.template @@ -0,0 +1,9 @@ +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +@interface $FILENAMESANSEXTENSION$ : Object +{ + +} + +@end diff --git a/rpcinfo.tproj/m.template b/rpcinfo.tproj/m.template new file mode 100644 index 0000000..1216fe5 --- /dev/null +++ b/rpcinfo.tproj/m.template @@ -0,0 +1,18 @@ +$$ Lines starting with $$ are not inserted into newly created files +$$ The following substitutions are made: +$$ +$$ $FILENAME$ e.g. foo.m +$$ $FILENAMESANSEXTENSION$ e.g. foo +$$ $DIRECTORY$ e.g. /tmp/MyNewApp +$$ $PROJECTNAME$ e.g. MyNewApp +$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj +$$ $USERNAME$ e.g. mwagner +$$ $DATE$ e.g. Jan-1-1994 +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import "$FILENAMESANSEXTENSION$.h" + +@implementation $FILENAMESANSEXTENSION$ + +@end diff --git a/rpcinfo.tproj/rpcinfo.c b/rpcinfo.tproj/rpcinfo.c new file mode 100644 index 0000000..3315bda --- /dev/null +++ b/rpcinfo.tproj/rpcinfo.c @@ -0,0 +1,690 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* @(#)rpcinfo.c 2.2 88/08/11 4.0 RPCSRC */ +#ifndef lint +static char sccsid[] = "@(#)rpcinfo.c 1.22 87/08/12 SMI"; +#endif + +/* + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +/* + * rpcinfo: ping a particular rpc program + * or dump the portmapper + */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAXHOSTLEN 256 + +#define MIN_VERS ((u_long) 0) +#define MAX_VERS ((u_long) 4294967295L) + +static void udpping(/*u_short portflag, int argc, char **argv*/); +static void tcpping(/*u_short portflag, int argc, char **argv*/); +static int pstatus(/*CLIENT *client, u_long prognum, u_long vers*/); +static void pmapdump(/*int argc, char **argv*/); +static bool_t reply_proc(/*void *res, struct sockaddr_in *who*/); +static void brdcst(/*int argc, char **argv*/); +static void deletereg(/* int argc, char **argv */) ; +static void usage(/*void*/); +static u_long getprognum(/*char *arg*/); +static u_long getvers(/*char *arg*/); +static void get_inet_address(/*struct sockaddr_in *addr, char *host*/); +extern u_long inet_addr(); /* in 4.2BSD, arpa/inet.h called that a in_addr */ +extern char *inet_ntoa(); + +/* + * Functions to be performed. + */ +#define NONE 0 /* no function */ +#define PMAPDUMP 1 /* dump portmapper registrations */ +#define TCPPING 2 /* ping TCP service */ +#define UDPPING 3 /* ping UDP service */ +#define BRDCST 4 /* ping broadcast UDP service */ +#define DELETES 5 /* delete registration for the service */ + +int +main(argc, argv) + int argc; + char **argv; +{ + register int c; + extern char *optarg; + extern int optind; + int errflg; + int function; + u_short portnum; + + function = NONE; + portnum = 0; + errflg = 0; + while ((c = getopt(argc, argv, "ptubdn:")) != EOF) { + switch (c) { + + case 'p': + if (function != NONE) + errflg = 1; + else + function = PMAPDUMP; + break; + + case 't': + if (function != NONE) + errflg = 1; + else + function = TCPPING; + break; + + case 'u': + if (function != NONE) + errflg = 1; + else + function = UDPPING; + break; + + case 'b': + if (function != NONE) + errflg = 1; + else + function = BRDCST; + break; + + case 'n': + portnum = (u_short) atoi(optarg); /* hope we don't get bogus # */ + break; + + case 'd': + if (function != NONE) + errflg = 1; + else + function = DELETES; + break; + + case '?': + errflg = 1; + } + } + + if (errflg || function == NONE) { + usage(); + return (1); + } + + switch (function) { + + case PMAPDUMP: + if (portnum != 0) { + usage(); + return (1); + } + pmapdump(argc - optind, argv + optind); + break; + + case UDPPING: + udpping(portnum, argc - optind, argv + optind); + break; + + case TCPPING: + tcpping(portnum, argc - optind, argv + optind); + break; + + case BRDCST: + if (portnum != 0) { + usage(); + return (1); + } + brdcst(argc - optind, argv + optind); + break; + + case DELETES: + deletereg(argc - optind, argv + optind); + break; + } + + return (0); +} + +static void +udpping(portnum, argc, argv) + u_short portnum; + int argc; + char **argv; +{ + struct timeval to; + struct sockaddr_in addr; + enum clnt_stat rpc_stat; + CLIENT *client; + u_long prognum, vers, minvers, maxvers; + int sock = RPC_ANYSOCK; + struct rpc_err rpcerr; + int failure; + + if (argc < 2 || argc > 3) { + usage(); + exit(1); + } + prognum = getprognum(argv[1]); + get_inet_address(&addr, argv[0]); + /* Open the socket here so it will survive calls to clnt_destroy */ + sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) { + perror("rpcinfo: socket"); + exit(1); + } + failure = 0; + if (argc == 2) { + /* + * A call to version 0 should fail with a program/version + * mismatch, and give us the range of versions supported. + */ + addr.sin_port = htons(portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create(&addr, prognum, (u_long)0, + to, &sock)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu is not available\n", + prognum); + exit(1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL, + xdr_void, (char *)NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) { + clnt_geterr(client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } else if (rpc_stat == RPC_SUCCESS) { + /* + * Oh dear, it DOES support version 0. + * Let's try version MAX_VERS. + */ + addr.sin_port = htons(portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create(&addr, prognum, MAX_VERS, + to, &sock)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, MAX_VERS); + exit(1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(client, NULLPROC, xdr_void, + (char *)NULL, xdr_void, (char *)NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) { + clnt_geterr(client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } else if (rpc_stat == RPC_SUCCESS) { + /* + * It also supports version MAX_VERS. + * Looks like we have a wise guy. + * OK, we give them information on all + * 4 billion versions they support... + */ + minvers = 0; + maxvers = MAX_VERS; + } else { + (void) pstatus(client, prognum, MAX_VERS); + exit(1); + } + } else { + (void) pstatus(client, prognum, (u_long)0); + exit(1); + } + clnt_destroy(client); + for (vers = minvers; vers <= maxvers; vers++) { + addr.sin_port = htons(portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create(&addr, prognum, vers, + to, &sock)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, vers); + exit(1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(client, NULLPROC, xdr_void, + (char *)NULL, xdr_void, (char *)NULL, to); + if (pstatus(client, prognum, vers) < 0) + failure = 1; + clnt_destroy(client); + } + } + else { + vers = getvers(argv[2]); + addr.sin_port = htons(portnum); + to.tv_sec = 5; + to.tv_usec = 0; + if ((client = clntudp_create(&addr, prognum, vers, + to, &sock)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, vers); + exit(1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL, + xdr_void, (char *)NULL, to); + if (pstatus(client, prognum, vers) < 0) + failure = 1; + } + (void) close(sock); /* Close it up again */ + if (failure) + exit(1); +} + +static void +tcpping(portnum, argc, argv) + u_short portnum; + int argc; + char **argv; +{ + struct timeval to; + struct sockaddr_in addr; + enum clnt_stat rpc_stat; + CLIENT *client; + u_long prognum, vers, minvers, maxvers; + int sock = RPC_ANYSOCK; + struct rpc_err rpcerr; + int failure; + + if (argc < 2 || argc > 3) { + usage(); + exit(1); + } + prognum = getprognum(argv[1]); + get_inet_address(&addr, argv[0]); + failure = 0; + if (argc == 2) { + /* + * A call to version 0 should fail with a program/version + * mismatch, and give us the range of versions supported. + */ + addr.sin_port = htons(portnum); + if ((client = clnttcp_create(&addr, prognum, MIN_VERS, + &sock, 0, 0)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu is not available\n", + prognum); + exit(1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(client, NULLPROC, xdr_void, (char *)NULL, + xdr_void, (char *)NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) { + clnt_geterr(client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } else if (rpc_stat == RPC_SUCCESS) { + /* + * Oh dear, it DOES support version 0. + * Let's try version MAX_VERS. + */ + addr.sin_port = htons(portnum); + if ((client = clnttcp_create(&addr, prognum, MAX_VERS, + &sock, 0, 0)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, MAX_VERS); + exit(1); + } + to.tv_sec = 10; + to.tv_usec = 0; + rpc_stat = clnt_call(client, NULLPROC, xdr_void, + (char *)NULL, xdr_void, (char *)NULL, to); + if (rpc_stat == RPC_PROGVERSMISMATCH) { + clnt_geterr(client, &rpcerr); + minvers = rpcerr.re_vers.low; + maxvers = rpcerr.re_vers.high; + } else if (rpc_stat == RPC_SUCCESS) { + /* + * It also supports version MAX_VERS. + * Looks like we have a wise guy. + * OK, we give them information on all + * 4 billion versions they support... + */ + minvers = 0; + maxvers = MAX_VERS; + } else { + (void) pstatus(client, prognum, MAX_VERS); + exit(1); + } + } else { + (void) pstatus(client, prognum, MIN_VERS); + exit(1); + } + clnt_destroy(client); + (void) close(sock); + sock = RPC_ANYSOCK; /* Re-initialize it for later */ + for (vers = minvers; vers <= maxvers; vers++) { + addr.sin_port = htons(portnum); + if ((client = clnttcp_create(&addr, prognum, vers, + &sock, 0, 0)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, vers); + exit(1); + } + to.tv_usec = 0; + to.tv_sec = 10; + rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL, + xdr_void, (char *)NULL, to); + if (pstatus(client, prognum, vers) < 0) + failure = 1; + clnt_destroy(client); + (void) close(sock); + sock = RPC_ANYSOCK; + } + } + else { + vers = getvers(argv[2]); + addr.sin_port = htons(portnum); + if ((client = clnttcp_create(&addr, prognum, vers, &sock, + 0, 0)) == NULL) { + clnt_pcreateerror("rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, vers); + exit(1); + } + to.tv_usec = 0; + to.tv_sec = 10; + rpc_stat = clnt_call(client, 0, xdr_void, (char *)NULL, + xdr_void, (char *)NULL, to); + if (pstatus(client, prognum, vers) < 0) + failure = 1; + } + if (failure) + exit(1); +} + +/* + * This routine should take a pointer to an "rpc_err" structure, rather than + * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to + * a CLIENT structure rather than a pointer to an "rpc_err" structure. + * As such, we have to keep the CLIENT structure around in order to print + * a good error message. + */ +static int +pstatus(client, prognum, vers) + register CLIENT *client; + u_long prognum; + u_long vers; +{ + struct rpc_err rpcerr; + + clnt_geterr(client, &rpcerr); + if (rpcerr.re_status != RPC_SUCCESS) { + clnt_perror(client, "rpcinfo"); + printf("program %lu version %lu is not available\n", + prognum, vers); + return (-1); + } else { + printf("program %lu version %lu ready and waiting\n", + prognum, vers); + return (0); + } +} + +static void +pmapdump(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in server_addr; + register struct hostent *hp; + struct pmaplist *head = NULL; + int socket = RPC_ANYSOCK; + struct timeval minutetimeout; + register CLIENT *client; + struct rpcent *rpc; + + if (argc > 1) { + usage(); + exit(1); + } + if (argc == 1) + get_inet_address(&server_addr, argv[0]); + else { + bzero((char *)&server_addr, sizeof server_addr); + server_addr.sin_family = AF_INET; + if ((hp = gethostbyname("localhost")) != NULL) + bcopy(hp->h_addr, (caddr_t)&server_addr.sin_addr, + hp->h_length); + else + server_addr.sin_addr.s_addr = inet_addr("0.0.0.0"); + } + minutetimeout.tv_sec = 60; + minutetimeout.tv_usec = 0; + server_addr.sin_port = htons(PMAPPORT); + if ((client = clnttcp_create(&server_addr, PMAPPROG, + PMAPVERS, &socket, 50, 500)) == NULL) { + clnt_pcreateerror("rpcinfo: can't contact portmapper"); + exit(1); + } + if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL, + xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) { + fprintf(stderr, "rpcinfo: can't contact portmapper: "); + clnt_perror(client, "rpcinfo"); + exit(1); + } + if (head == NULL) { + printf("No remote programs registered.\n"); + } else { + printf(" program vers proto port\n"); + for (; head != NULL; head = head->pml_next) { + printf("%10ld%5ld", + head->pml_map.pm_prog, + head->pml_map.pm_vers); + if (head->pml_map.pm_prot == IPPROTO_UDP) + printf("%6s", "udp"); + else if (head->pml_map.pm_prot == IPPROTO_TCP) + printf("%6s", "tcp"); + else + printf("%6ld", head->pml_map.pm_prot); + printf("%7ld", head->pml_map.pm_port); + rpc = getrpcbynumber(head->pml_map.pm_prog); + if (rpc) + printf(" %s\n", rpc->r_name); + else + printf("\n"); + } + } +} + +/* + * reply_proc collects replies from the broadcast. + * to get a unique list of responses the output of rpcinfo should + * be piped through sort(1) and then uniq(1). + */ + +/*ARGSUSED*/ +static bool_t +reply_proc(res, who) + void *res; /* Nothing comes back */ + struct sockaddr_in *who; /* Who sent us the reply */ +{ + register struct hostent *hp; + + hp = gethostbyaddr((char *) &who->sin_addr, sizeof who->sin_addr, + AF_INET); + printf("%s %s\n", inet_ntoa(who->sin_addr), + (hp == NULL) ? "(unknown)" : hp->h_name); + return(FALSE); +} + +static void +brdcst(argc, argv) + int argc; + char **argv; +{ + enum clnt_stat rpc_stat; + u_long prognum, vers; + + if (argc != 2) { + usage(); + exit(1); + } + prognum = getprognum(argv[0]); + vers = getvers(argv[1]); + rpc_stat = clnt_broadcast(prognum, vers, NULLPROC, xdr_void, + (char *)NULL, xdr_void, (char *)NULL, reply_proc); + if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT)) { + fprintf(stderr, "rpcinfo: broadcast failed: %s\n", + clnt_sperrno(rpc_stat)); + exit(1); + } + exit(0); +} + +static void +deletereg(argc, argv) + int argc; + char **argv; +{ u_long prog_num, version_num ; + + if (argc != 2) { + usage() ; + exit(1) ; + } + if (getuid()) { /* This command allowed only to root */ + fprintf(stderr, "Sorry. You are not root\n") ; + exit(1) ; + } + prog_num = getprognum(argv[0]); + version_num = getvers(argv[1]); + if ((pmap_unset(prog_num, version_num)) == 0) { + fprintf(stderr, "rpcinfo: Could not delete registration for prog %s version %s\n", + argv[0], argv[1]) ; + exit(1) ; + } +} + +static void +usage() +{ + fprintf(stderr, "Usage: rpcinfo [ -n portnum ] -u host prognum [ versnum ]\n"); + fprintf(stderr, " rpcinfo [ -n portnum ] -t host prognum [ versnum ]\n"); + fprintf(stderr, " rpcinfo -p [ host ]\n"); + fprintf(stderr, " rpcinfo -b prognum versnum\n"); + fprintf(stderr, " rpcinfo -d prognum versnum\n") ; +} + +static u_long +getprognum(arg) + char *arg; +{ + register struct rpcent *rpc; + register u_long prognum; + + if (isalpha(*arg)) { + rpc = getrpcbyname(arg); + if (rpc == NULL) { + fprintf(stderr, "rpcinfo: %s is unknown service\n", + arg); + exit(1); + } + prognum = rpc->r_number; + } else { + prognum = (u_long) atoi(arg); + } + + return (prognum); +} + +static u_long +getvers(arg) + char *arg; +{ + register u_long vers; + + vers = (int) atoi(arg); + return (vers); +} + +static void +get_inet_address(addr, host) + struct sockaddr_in *addr; + char *host; +{ + register struct hostent *hp; + + bzero((char *)addr, sizeof *addr); + addr->sin_addr.s_addr = (u_long) inet_addr(host); + if (addr->sin_addr.s_addr == -1 || addr->sin_addr.s_addr == 0) { + if ((hp = gethostbyname(host)) == NULL) { + fprintf(stderr, "rpcinfo: %s is unknown host\n", host); + exit(1); + } + bcopy(hp->h_addr, (char *)&addr->sin_addr, hp->h_length); + } + addr->sin_family = AF_INET; +} diff --git a/rsh.tproj/Makefile b/rsh.tproj/Makefile new file mode 100644 index 0000000..c387527 --- /dev/null +++ b/rsh.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rsh + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = pathnames.h + +CFILES = rsh.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rsh.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rsh.tproj/Makefile.postamble b/rsh.tproj/Makefile.postamble new file mode 100644 index 0000000..625a231 --- /dev/null +++ b/rsh.tproj/Makefile.postamble @@ -0,0 +1,5 @@ +VPATH += :../rlogin.tproj +INSTALL_PERMISSIONS = 4555 + +after_install:: + $(CHFLAGS) schg $(DSTROOT)$(INSTALLDIR)/$(NAME) diff --git a/rsh.tproj/Makefile.preamble b/rsh.tproj/Makefile.preamble new file mode 100644 index 0000000..87a4321 --- /dev/null +++ b/rsh.tproj/Makefile.preamble @@ -0,0 +1,4 @@ +RLOGIN_CFILES = krcmd.c des_rw.c +OTHER_OFILES = $(RLOGIN_CFILES:.c=.o) +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/rsh.tproj/PB.project b/rsh.tproj/PB.project new file mode 100644 index 0000000..33594fc --- /dev/null +++ b/rsh.tproj/PB.project @@ -0,0 +1,30 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + CLASSES = (); + FRAMEWORKS = (); + H_FILES = (pathnames.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rsh.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rsh.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = rsh; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = rsh; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rsh; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = rsh; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rsh.tproj/pathnames.h b/rsh.tproj/pathnames.h new file mode 100644 index 0000000..812b0d0 --- /dev/null +++ b/rsh.tproj/pathnames.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#define _PATH_RLOGIN "/usr/bin/rlogin" diff --git a/rsh.tproj/rsh.1 b/rsh.tproj/rsh.1 new file mode 100644 index 0000000..78ec2f1 --- /dev/null +++ b/rsh.tproj/rsh.1 @@ -0,0 +1,187 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rsh.1 8.2 (Berkeley) 4/29/95 +.\" +.Dd April 29, 1995 +.Dt RSH 1 +.Os BSD 4.2 +.Sh NAME +.Nm rsh +.Nd remote shell +.Sh SYNOPSIS +.Nm rsh +.Op Fl Kdnx +.Op Fl k Ar realm +.Op Fl l Ar username +.Ar host +.Nm rsh +.Op Fl Kdnx +.Op Fl k Ar realm +.Ar username@host +.Op command +.Sh DESCRIPTION +.Nm Rsh +executes +.Ar command +on +.Ar host . +.Pp +.Nm Rsh +copies its standard input to the remote command, the standard +output of the remote command to its standard output, and the +standard error of the remote command to its standard error. +Interrupt, quit and terminate signals are propagated to the remote +command; +.Nm rsh +normally terminates when the remote command does. +The options are as follows: +.Bl -tag -width flag +.It Fl K +The +.Fl K +option turns off all Kerberos authentication. +.It Fl d +The +.Fl d +option turns on socket debugging (using +.Xr setsockopt 2 ) +on the +.Tn TCP +sockets used for communication with the remote host. +.It Fl k +The +.Fl k +option causes +.Nm rsh +to obtain tickets for the remote host in +.Ar realm +instead of the remote host's realm as determined by +.Xr krb_realmofhost 3 . +.It Fl l +By default, the remote username is the same as the local username. +The +.Fl l +option or the +.Pa username@host +format allow the remote name to be specified. +Kerberos authentication is used, and authorization is determined +as in +.Xr rlogin 1 . +.It Fl n +The +.Fl n +option redirects input from the special device +.Pa /dev/null +(see the +.Sx BUGS +section of this manual page). +.It Fl x +The +.Fl x +option turns on +.Tn DES +encryption for all data exchange. +This may introduce a significant delay in response time. +.El +.Pp +If no +.Ar command +is specified, you will be logged in on the remote host using +.Xr rlogin 1 . +.Pp +Shell metacharacters which are not quoted are interpreted on local machine, +while quoted metacharacters are interpreted on the remote machine. +For example, the command +.Pp +.Dl rsh otherhost cat remotefile >> localfile +.Pp +appends the remote file +.Ar remotefile +to the local file +.Ar localfile , +while +.Pp +.Dl rsh otherhost cat remotefile \&">>\&" other_remotefile +.Pp +appends +.Ar remotefile +to +.Ar other_remotefile . +.\" .Pp +.\" Many sites specify a large number of host names as commands in the +.\" directory /usr/hosts. +.\" If this directory is included in your search path, you can use the +.\" shorthand ``host command'' for the longer form ``rsh host command''. +.Sh FILES +.Bl -tag -width /etc/hosts -compact +.It Pa /etc/hosts +.El +.Sh SEE ALSO +.Xr rlogin 1 , +.Xr kerberos 3 , +.Xr krb_sendauth 3 , +.Xr krb_realmofhost 3 +.Sh HISTORY +The +.Nm rsh +command appeared in +.Bx 4.2 . +.Sh BUGS +If you are using +.Xr csh 1 +and put a +.Nm rsh +in the background without redirecting its input away from the terminal, +it will block even if no reads are posted by the remote command. +If no input is desired you should redirect the input of +.Nm rsh +to +.Pa /dev/null +using the +.Fl n +option. +.Pp +You cannot run an interactive command +(like +.Xr rogue 6 +or +.Xr vi 1 ) +using +.Nm rsh ; +use +.Xr rlogin 1 +instead. +.Pp +Stop signals stop the local +.Nm rsh +process only; this is arguably wrong, but currently hard to fix for reasons +too complicated to explain here. diff --git a/rsh.tproj/rsh.c b/rsh.tproj/rsh.c new file mode 100644 index 0000000..9474164 --- /dev/null +++ b/rsh.tproj/rsh.c @@ -0,0 +1,504 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1983, 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * $Source: /cvs/Darwin/Commands/NeXT/network_cmds/rsh.tproj/rsh.c,v $ + * $Header: /cvs/Darwin/Commands/NeXT/network_cmds/rsh.tproj/rsh.c,v 1.1.1.1 1999/05/02 03:58:17 wsanchez Exp $ + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pathnames.h" + +#ifdef KERBEROS +#include +#include + +CREDENTIALS cred; +Key_schedule schedule; +int use_kerberos = 1, doencrypt; +char dst_realm_buf[REALM_SZ], *dest_realm; +extern char *krb_realmofhost(); +#endif + +/* + * rsh - remote shell + */ +int rfd2; + +char *copyargs __P((char **)); +void sendsig __P((int)); +void talk __P((int, long, pid_t, int)); +void usage __P((void)); +void warning __P(()); + +int +main(argc, argv) + int argc; + char **argv; +{ + struct passwd *pw; + struct servent *sp; + long omask; + int argoff, asrsh, ch, dflag, nflag, one, rem; + pid_t pid; + uid_t uid; + char *args, *host, *p, *user; + + argoff = asrsh = dflag = nflag = 0; + one = 1; + host = user = NULL; + + /* if called as something other than "rsh", use it as the host name */ + if (p = strrchr(argv[0], '/')) + ++p; + else + p = argv[0]; + if (strcmp(p, "rsh")) + host = p; + else + asrsh = 1; + + /* handle "rsh host flags" */ + if (!host && argc > 2 && argv[1][0] != '-') { + host = argv[1]; + argoff = 1; + } + +#ifdef KERBEROS +#ifdef CRYPT +#define OPTIONS "8KLdek:l:nwx" +#else +#define OPTIONS "8KLdek:l:nw" +#endif +#else +#define OPTIONS "8KLdel:nw" +#endif + while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) + switch(ch) { + case 'K': +#ifdef KERBEROS + use_kerberos = 0; +#endif + break; + case 'L': /* -8Lew are ignored to allow rlogin aliases */ + case 'e': + case 'w': + case '8': + break; + case 'd': + dflag = 1; + break; + case 'l': + user = optarg; + break; +#ifdef KERBEROS + case 'k': + dest_realm = dst_realm_buf; + strncpy(dest_realm, optarg, REALM_SZ); + break; +#endif + case 'n': + nflag = 1; + break; +#ifdef KERBEROS +#ifdef CRYPT + case 'x': + doencrypt = 1; + des_set_key(cred.session, schedule); + break; +#endif +#endif + case '?': + default: + usage(); + } + optind += argoff; + + /* if haven't gotten a host yet, do so */ + if (!host && !(host = argv[optind++])) + usage(); + + /* if no further arguments, must have been called as rlogin. */ + if (!argv[optind]) { + if (asrsh) + *argv = "rlogin"; + execv(_PATH_RLOGIN, argv); + err(1, "can't exec %s", _PATH_RLOGIN); + } + + argc -= optind; + argv += optind; + + if (!(pw = getpwuid(uid = getuid()))) + errx(1, "unknown user id"); + /* Accept user1@host format, though "-l user2" overrides user1 */ + p = strchr(host, '@'); + if (p) { + *p = '\0'; + if (!user && p > host) + user = host; + host = p + 1; + if (*host == '\0') + usage(); + } + if (!user) + user = pw->pw_name; + +#ifdef KERBEROS +#ifdef CRYPT + /* -x turns off -n */ + if (doencrypt) + nflag = 0; +#endif +#endif + + args = copyargs(argv); + + sp = NULL; +#ifdef KERBEROS + if (use_kerberos) { + sp = getservbyname((doencrypt ? "ekshell" : "kshell"), "tcp"); + if (sp == NULL) { + use_kerberos = 0; + warning("can't get entry for %s/tcp service", + doencrypt ? "ekshell" : "kshell"); + } + } +#endif + if (sp == NULL) + sp = getservbyname("shell", "tcp"); + if (sp == NULL) + errx(1, "shell/tcp: unknown service"); + +#ifdef KERBEROS +try_connect: + if (use_kerberos) { + struct hostent *hp; + + /* fully qualify hostname (needed for krb_realmofhost) */ + hp = gethostbyname(host); + if (hp != NULL && !(host = strdup(hp->h_name))) + err(1, NULL); + + rem = KSUCCESS; + errno = 0; + if (dest_realm == NULL) + dest_realm = krb_realmofhost(host); + +#ifdef CRYPT + if (doencrypt) + rem = krcmd_mutual(&host, sp->s_port, user, args, + &rfd2, dest_realm, &cred, schedule); + else +#endif + rem = krcmd(&host, sp->s_port, user, args, &rfd2, + dest_realm); + if (rem < 0) { + use_kerberos = 0; + sp = getservbyname("shell", "tcp"); + if (sp == NULL) + errx(1, "shell/tcp: unknown service"); + if (errno == ECONNREFUSED) + warning("remote host doesn't support Kerberos"); + if (errno == ENOENT) + warning("can't provide Kerberos auth data"); + goto try_connect; + } + } else { + if (doencrypt) + errx(1, "the -x flag requires Kerberos authentication"); + rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); + } +#else + rem = rcmd(&host, sp->s_port, pw->pw_name, user, args, &rfd2); +#endif + + if (rem < 0) + exit(1); + + if (rfd2 < 0) + errx(1, "can't establish stderr"); + if (dflag) { + if (setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, + sizeof(one)) < 0) + warn("setsockopt"); + if (setsockopt(rfd2, SOL_SOCKET, SO_DEBUG, &one, + sizeof(one)) < 0) + warn("setsockopt"); + } + + (void)setuid(uid); + omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM)); + if (signal(SIGINT, SIG_IGN) != SIG_IGN) + (void)signal(SIGINT, sendsig); + if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) + (void)signal(SIGQUIT, sendsig); + if (signal(SIGTERM, SIG_IGN) != SIG_IGN) + (void)signal(SIGTERM, sendsig); + + if (!nflag) { + pid = fork(); + if (pid < 0) + err(1, "fork"); + } + +#ifdef KERBEROS +#ifdef CRYPT + if (!doencrypt) +#endif +#endif + { + (void)ioctl(rfd2, FIONBIO, &one); + (void)ioctl(rem, FIONBIO, &one); + } + + talk(nflag, omask, pid, rem); + + if (!nflag) + (void)kill(pid, SIGKILL); + exit(0); +} + +void +talk(nflag, omask, pid, rem) + int nflag; + long omask; + pid_t pid; + int rem; +{ + int cc, wc; + fd_set readfrom, ready, rembits; + char *bp, buf[BUFSIZ]; + + if (!nflag && pid == 0) { + (void)close(rfd2); + +reread: errno = 0; + if ((cc = read(0, buf, sizeof buf)) <= 0) + goto done; + bp = buf; + +rewrite: + FD_ZERO(&rembits); + FD_SET(rem, &rembits); + if (select(16, 0, &rembits, 0, 0) < 0) { + if (errno != EINTR) + err(1, "select"); + goto rewrite; + } + if (!FD_ISSET(rem, &rembits)) + goto rewrite; +#ifdef KERBEROS +#ifdef CRYPT + if (doencrypt) + wc = des_write(rem, bp, cc); + else +#endif +#endif + wc = write(rem, bp, cc); + if (wc < 0) { + if (errno == EWOULDBLOCK) + goto rewrite; + goto done; + } + bp += wc; + cc -= wc; + if (cc == 0) + goto reread; + goto rewrite; +done: + (void)shutdown(rem, 1); + exit(0); + } + + (void)sigsetmask(omask); + FD_ZERO(&readfrom); + FD_SET(rfd2, &readfrom); + FD_SET(rem, &readfrom); + do { + ready = readfrom; + if (select(16, &ready, 0, 0, 0) < 0) { + if (errno != EINTR) + err(1, "select"); + continue; + } + if (FD_ISSET(rfd2, &ready)) { + errno = 0; +#ifdef KERBEROS +#ifdef CRYPT + if (doencrypt) + cc = des_read(rfd2, buf, sizeof buf); + else +#endif +#endif + cc = read(rfd2, buf, sizeof buf); + if (cc <= 0) { + if (errno != EWOULDBLOCK) + FD_CLR(rfd2, &readfrom); + } else + (void)write(2, buf, cc); + } + if (FD_ISSET(rem, &ready)) { + errno = 0; +#ifdef KERBEROS +#ifdef CRYPT + if (doencrypt) + cc = des_read(rem, buf, sizeof buf); + else +#endif +#endif + cc = read(rem, buf, sizeof buf); + if (cc <= 0) { + if (errno != EWOULDBLOCK) + FD_CLR(rem, &readfrom); + } else + (void)write(1, buf, cc); + } + } while (FD_ISSET(rfd2, &readfrom) || FD_ISSET(rem, &readfrom)); +} + +void +sendsig(sig) + int sig; +{ + char signo; + + signo = sig; +#ifdef KERBEROS +#ifdef CRYPT + if (doencrypt) + (void)des_write(rfd2, &signo, 1); + else +#endif +#endif + (void)write(rfd2, &signo, 1); +} + +#ifdef KERBEROS +/* VARARGS */ +void +warning(va_alist) +va_dcl +{ + va_list ap; + char *fmt; + + (void)fprintf(stderr, "rsh: warning, using standard rsh: "); + va_start(ap); + fmt = va_arg(ap, char *); + vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, ".\n"); +} +#endif + +char * +copyargs(argv) + char **argv; +{ + int cc; + char **ap, *args, *p; + + cc = 0; + for (ap = argv; *ap; ++ap) + cc += strlen(*ap) + 1; + if (!(args = malloc((u_int)cc))) + err(1, NULL); + for (p = args, ap = argv; *ap; ++ap) { + (void)strcpy(p, *ap); + for (p = strcpy(p, *ap); *p; ++p); + if (ap[1]) + *p++ = ' '; + } + return (args); +} + +void +usage() +{ + + (void)fprintf(stderr, + "usage: rsh [-nd%s]%s[-l login] [login@]host [command]\n", +#ifdef KERBEROS +#ifdef CRYPT + "x", " [-k realm] "); +#else + "", " [-k realm] "); +#endif +#else + "", " "); +#endif + exit(1); +} diff --git a/rshd.tproj/Makefile b/rshd.tproj/Makefile new file mode 100644 index 0000000..3ebcdb8 --- /dev/null +++ b/rshd.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rshd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = rshd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rshd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rshd.tproj/Makefile.postamble b/rshd.tproj/Makefile.postamble new file mode 100644 index 0000000..fd0e632 --- /dev/null +++ b/rshd.tproj/Makefile.postamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + +VPATH += :../rlogin.tproj + diff --git a/rshd.tproj/Makefile.preamble b/rshd.tproj/Makefile.preamble new file mode 100644 index 0000000..6301c77 --- /dev/null +++ b/rshd.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +OTHER_OFILES = des_rw.o + +-include ../Makefile.include diff --git a/rshd.tproj/PB.project b/rshd.tproj/PB.project new file mode 100644 index 0000000..1252083 --- /dev/null +++ b/rshd.tproj/PB.project @@ -0,0 +1,42 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rshd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rshd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rshd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rshd.tproj/rshd.8 b/rshd.tproj/rshd.8 new file mode 100644 index 0000000..82e1991 --- /dev/null +++ b/rshd.tproj/rshd.8 @@ -0,0 +1,209 @@ +.\" Copyright (c) 1983, 1989, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rshd.8 8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt RSHD 8 +.Os BSD 4.2 +.Sh NAME +.Nm rshd +.Nd remote shell server +.Sh SYNOPSIS +.Nm rshd +.Op Fl alnL +.Sh DESCRIPTION +The +.Nm rshd +server +is the server for the +.Xr rcmd 3 +routine and, consequently, for the +.Xr rsh 1 +program. The server provides remote execution facilities +with authentication based on privileged port numbers from trusted hosts. +.Pp +The +.Nm rshd +server +listens for service requests at the port indicated in +the ``cmd'' service specification; see +.Xr services 5 . +When a service request is received the following protocol +is initiated: +.Bl -enum +.It +The server checks the client's source port. +If the port is not in the range 512-1023, the server +aborts the connection. +.It +The server reads characters from the socket up +to a null (`\e0') byte. The resultant string is +interpreted as an +.Tn ASCII +number, base 10. +.It +If the number received in step 2 is non-zero, +it is interpreted as the port number of a secondary +stream to be used for the +.Em stderr . +A second connection is then created to the specified +port on the client's machine. The source port of this +second connection is also in the range 512-1023. +.It +The server checks the client's source address +and requests the corresponding host name (see +.Xr gethostbyaddr 3 , +.Xr hosts 5 +and +.Xr named 8 ) . +If the hostname cannot be determined, +the dot-notation representation of the host address is used. +If the hostname is in the same domain as the server (according to +the last two components of the domain name), +or if the +.Fl a +option is given, +the addresses for the hostname are requested, +verifying that the name and address correspond. +If address verification fails, the connection is aborted +with the message, ``Host address mismatch.'' +.It +A null terminated user name of at most 16 characters +is retrieved on the initial socket. This user name +is interpreted as the user identity on the +.Em client Ns 's +machine. +.It +A null terminated user name of at most 16 characters +is retrieved on the initial socket. This user name +is interpreted as a user identity to use on the +.Sy server Ns 's +machine. +.It +A null terminated command to be passed to a +shell is retrieved on the initial socket. The length of +the command is limited by the upper bound on the size of +the system's argument list. +.It +.Nm Rshd +then validates the user using +.Xr ruserok 3 , +which uses the file +.Pa /etc/hosts.equiv +and the +.Pa .rhosts +file found in the user's home directory. The +.Fl l +option prevents +.Xr ruserok 3 +from doing any validation based on the user's ``.rhosts'' file, +unless the user is the superuser. +.It +If the file +.Pa /etc/nologin +exists and the user is not the superuser, +the connection is closed. +.It +A null byte is returned on the initial socket +and the command line is passed to the normal login +shell of the user. The +shell inherits the network connections established +by +.Nm rshd . +.El +.Pp +Transport-level keepalive messages are enabled unless the +.Fl n +option is present. +The use of keepalive messages allows sessions to be timed out +if the client crashes or becomes unreachable. +.Pp +The +.Fl L +option causes all successful accesses to be logged to +.Xr syslogd 8 +as +.Li auth.info +messages. +.Sh DIAGNOSTICS +Except for the last one listed below, +all diagnostic messages +are returned on the initial socket, +after which any network connections are closed. +An error is indicated by a leading byte with a value of +1 (0 is returned in step 10 above upon successful completion +of all the steps prior to the execution of the login shell). +.Bl -tag -width indent +.It Sy Locuser too long. +The name of the user on the client's machine is +longer than 16 characters. +.It Sy Ruser too long. +The name of the user on the remote machine is +longer than 16 characters. +.It Sy Command too long . +The command line passed exceeds the size of the argument +list (as configured into the system). +.It Sy Login incorrect. +No password file entry for the user name existed. +.It Sy Remote directory. +The +.Xr chdir +command to the home directory failed. +.It Sy Permission denied. +The authentication procedure described above failed. +.It Sy Can't make pipe. +The pipe needed for the +.Em stderr , +wasn't created. +.It Sy Can't fork; try again. +A +.Xr fork +by the server failed. +.It Sy : ... +The user's login shell could not be started. This message is returned +on the connection associated with the +.Em stderr , +and is not preceded by a flag byte. +.El +.Sh SEE ALSO +.Xr rsh 1 , +.Xr rcmd 3 , +.Xr ruserok 3 +.Sh BUGS +The authentication procedure used here assumes the integrity +of each client machine and the connecting medium. This is +insecure, but is useful in an ``open'' environment. +.Pp +A facility to allow all data exchanges to be encrypted should be +present. +.Pp +A more extensible protocol (such as Telnet) should be used. diff --git a/rshd.tproj/rshd.c b/rshd.tproj/rshd.c new file mode 100644 index 0000000..7e8d10c --- /dev/null +++ b/rshd.tproj/rshd.c @@ -0,0 +1,809 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1988, 1989, 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1989, 1992, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rshd.c 8.2 (Berkeley) 4/6/94"; +#endif /* not lint */ + +/* + * remote shell server: + * [port]\0 + * remuser\0 + * locuser\0 + * command\0 + * data + */ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int keepalive = 1; +int check_all; +int log_success; /* If TRUE, log all successful accesses */ +int sent_null; + +void doit __P((struct sockaddr_in *)); +void error __P((const char *, ...)); +void getstr __P((char *, int, char *)); +int local_domain __P((char *)); +char *topdomain __P((char *)); +void usage __P((void)); + +#ifdef KERBEROS +#include +#include +#define VERSION_SIZE 9 +#define SECURE_MESSAGE "This rsh session is using DES encryption for all transmissions.\r\n" +#define OPTIONS "alnkvxL" +char authbuf[sizeof(AUTH_DAT)]; +char tickbuf[sizeof(KTEXT_ST)]; +int doencrypt, use_kerberos, vacuous; +Key_schedule schedule; +#else +#define OPTIONS "alnL" +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern int __check_rhosts_file; + struct linger linger; + int ch, on = 1, fromlen; + struct sockaddr_in from; + + openlog("rshd", LOG_PID | LOG_ODELAY, LOG_DAEMON); + + opterr = 0; + while ((ch = getopt(argc, argv, OPTIONS)) != EOF) + switch (ch) { + case 'a': + check_all = 1; + break; + case 'l': + __check_rhosts_file = 0; + break; + case 'n': + keepalive = 0; + break; +#ifdef KERBEROS + case 'k': + use_kerberos = 1; + break; + + case 'v': + vacuous = 1; + break; + +#ifdef CRYPT + case 'x': + doencrypt = 1; + break; +#endif +#endif + case 'L': + log_success = 1; + break; + case '?': + default: + usage(); + break; + } + + argc -= optind; + argv += optind; + +#ifdef KERBEROS + if (use_kerberos && vacuous) { + syslog(LOG_ERR, "only one of -k and -v allowed"); + exit(2); + } +#ifdef CRYPT + if (doencrypt && !use_kerberos) { + syslog(LOG_ERR, "-k is required for -x"); + exit(2); + } +#endif +#endif + + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + _exit(1); + } + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, + sizeof(on)) < 0) + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); + linger.l_onoff = 1; + linger.l_linger = 60; /* XXX */ + if (setsockopt(0, SOL_SOCKET, SO_LINGER, (char *)&linger, + sizeof (linger)) < 0) + syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); + doit(&from); + /* NOTREACHED */ +} + +char username[20] = "USER="; +char homedir[64] = "HOME="; +char shell[64] = "SHELL="; +char path[100] = "PATH="; +char *envinit[] = + {homedir, shell, path, username, 0}; +#ifdef __APPLE__ +extern +#endif +char **environ; + +void +doit(fromp) + struct sockaddr_in *fromp; +{ + extern char *__rcmd_errstr; /* syslog hook from libc/net/rcmd.c. */ + struct hostent *hp; + struct passwd *pwd; + u_short port; + fd_set ready, readfrom; + int cc, nfd, pv[2], pid, s; + int one = 1; + char *hostname, *errorstr, *errorhost; + char *cp, sig, buf[BUFSIZ]; + char cmdbuf[NCARGS+1], locuser[16], remuser[16]; + char remotehost[2 * MAXHOSTNAMELEN + 1]; + +#ifdef KERBEROS + AUTH_DAT *kdata = (AUTH_DAT *) NULL; + KTEXT ticket = (KTEXT) NULL; + char instance[INST_SZ], version[VERSION_SIZE]; + struct sockaddr_in fromaddr; + int rc; + long authopts; + int pv1[2], pv2[2]; + fd_set wready, writeto; + + fromaddr = *fromp; +#endif + + (void) signal(SIGINT, SIG_DFL); + (void) signal(SIGQUIT, SIG_DFL); + (void) signal(SIGTERM, SIG_DFL); +#ifdef DEBUG + { int t = open(_PATH_TTY, 2); + if (t >= 0) { + ioctl(t, TIOCNOTTY, (char *)0); + (void) close(t); + } + } +#endif + fromp->sin_port = ntohs((u_short)fromp->sin_port); + if (fromp->sin_family != AF_INET) { + syslog(LOG_ERR, "malformed \"from\" address (af %d)", + fromp->sin_family); + exit(1); + } +#ifdef IP_OPTIONS + { + u_char optbuf[BUFSIZ/3], *cp; + char lbuf[BUFSIZ], *lp; + int optsize = sizeof(optbuf), ipproto; + struct protoent *ip; + + if ((ip = getprotobyname("ip")) != NULL) + ipproto = ip->p_proto; + else + ipproto = IPPROTO_IP; + if (!getsockopt(0, ipproto, IP_OPTIONS, (char *)optbuf, &optsize) && + optsize != 0) { + lp = lbuf; + for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3) + sprintf(lp, " %2.2x", *cp); + syslog(LOG_NOTICE, + "Connection received from %s using IP options (ignored):%s", + inet_ntoa(fromp->sin_addr), lbuf); + if (setsockopt(0, ipproto, IP_OPTIONS, + (char *)NULL, optsize) != 0) { + syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m"); + exit(1); + } + } + } +#endif + +#ifdef KERBEROS + if (!use_kerberos) +#endif + if (fromp->sin_port >= IPPORT_RESERVED || + fromp->sin_port < IPPORT_RESERVED/2) { + syslog(LOG_NOTICE|LOG_AUTH, + "Connection from %s on illegal port %u", + inet_ntoa(fromp->sin_addr), + fromp->sin_port); + exit(1); + } + + (void) alarm(60); + port = 0; + for (;;) { + char c; + if ((cc = read(STDIN_FILENO, &c, 1)) != 1) { + if (cc < 0) + syslog(LOG_NOTICE, "read: %m"); + shutdown(0, 1+1); + exit(1); + } + if (c== 0) + break; + port = port * 10 + c - '0'; + } + + (void) alarm(0); + if (port != 0) { + int lport = IPPORT_RESERVED - 1; + s = rresvport(&lport); + if (s < 0) { + syslog(LOG_ERR, "can't get stderr port: %m"); + exit(1); + } +#ifdef KERBEROS + if (!use_kerberos) +#endif + if (port >= IPPORT_RESERVED) { + syslog(LOG_ERR, "2nd port not reserved"); + exit(1); + } + fromp->sin_port = htons(port); + if (connect(s, (struct sockaddr *)fromp, sizeof (*fromp)) < 0) { + syslog(LOG_INFO, "connect second port %d: %m", port); + exit(1); + } + } + +#ifdef KERBEROS + if (vacuous) { + error("rshd: remote host requires Kerberos authentication\n"); + exit(1); + } +#endif + +#ifdef notdef + /* from inetd, socket is already on 0, 1, 2 */ + dup2(f, 0); + dup2(f, 1); + dup2(f, 2); +#endif + errorstr = NULL; + hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (struct in_addr), + fromp->sin_family); + if (hp) { + /* + * If name returned by gethostbyaddr is in our domain, + * attempt to verify that we haven't been fooled by someone + * in a remote net; look up the name and check that this + * address corresponds to the name. + */ + hostname = hp->h_name; +#ifdef KERBEROS + if (!use_kerberos) +#endif + if (check_all || local_domain(hp->h_name)) { + strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1); + remotehost[sizeof(remotehost) - 1] = 0; + errorhost = remotehost; + hp = gethostbyname(remotehost); + if (hp == NULL) { + syslog(LOG_INFO, + "Couldn't look up address for %s", + remotehost); + errorstr = + "Couldn't look up address for your host (%s)\n"; + hostname = inet_ntoa(fromp->sin_addr); + } else for (; ; hp->h_addr_list++) { + if (hp->h_addr_list[0] == NULL) { + syslog(LOG_NOTICE, + "Host addr %s not listed for host %s", + inet_ntoa(fromp->sin_addr), + hp->h_name); + errorstr = + "Host address mismatch for %s\n"; + hostname = inet_ntoa(fromp->sin_addr); + break; + } + if (!bcmp(hp->h_addr_list[0], + (caddr_t)&fromp->sin_addr, + sizeof(fromp->sin_addr))) { + hostname = hp->h_name; + break; + } + } + } + } else + errorhost = hostname = inet_ntoa(fromp->sin_addr); + +#ifdef KERBEROS + if (use_kerberos) { + kdata = (AUTH_DAT *) authbuf; + ticket = (KTEXT) tickbuf; + authopts = 0L; + strcpy(instance, "*"); + version[VERSION_SIZE - 1] = '\0'; +#ifdef CRYPT + if (doencrypt) { + struct sockaddr_in local_addr; + rc = sizeof(local_addr); + if (getsockname(0, (struct sockaddr *)&local_addr, + &rc) < 0) { + syslog(LOG_ERR, "getsockname: %m"); + error("rshd: getsockname: %m"); + exit(1); + } + authopts = KOPT_DO_MUTUAL; + rc = krb_recvauth(authopts, 0, ticket, + "rcmd", instance, &fromaddr, + &local_addr, kdata, "", schedule, + version); + des_set_key(kdata->session, schedule); + } else +#endif + rc = krb_recvauth(authopts, 0, ticket, "rcmd", + instance, &fromaddr, + (struct sockaddr_in *) 0, + kdata, "", (bit_64 *) 0, version); + if (rc != KSUCCESS) { + error("Kerberos authentication failure: %s\n", + krb_err_txt[rc]); + exit(1); + } + } else +#endif + getstr(remuser, sizeof(remuser), "remuser"); + + getstr(locuser, sizeof(locuser), "locuser"); + getstr(cmdbuf, sizeof(cmdbuf), "command"); + setpwent(); + pwd = getpwnam(locuser); + if (pwd == NULL) { + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: unknown login. cmd='%.80s'", + remuser, hostname, locuser, cmdbuf); + if (errorstr == NULL) + errorstr = "Login incorrect.\n"; + goto fail; + } + if (chdir(pwd->pw_dir) < 0) { + (void) chdir("/"); +#ifdef notdef + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: no home directory. cmd='%.80s'", + remuser, hostname, locuser, cmdbuf); + error("No remote directory.\n"); + exit(1); +#endif + } + +#ifdef KERBEROS + if (use_kerberos) { + if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0') { + if (kuserok(kdata, locuser) != 0) { + syslog(LOG_INFO|LOG_AUTH, + "Kerberos rsh denied to %s.%s@%s", + kdata->pname, kdata->pinst, kdata->prealm); + error("Permission denied.\n"); + exit(1); + } + } + } else +#endif + + if (errorstr || + pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' && + iruserok(fromp->sin_addr.s_addr, pwd->pw_uid == 0, + remuser, locuser) < 0) { + if (__rcmd_errstr) + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: permission denied (%s). cmd='%.80s'", + remuser, hostname, locuser, __rcmd_errstr, + cmdbuf); + else + syslog(LOG_INFO|LOG_AUTH, + "%s@%s as %s: permission denied. cmd='%.80s'", + remuser, hostname, locuser, cmdbuf); +fail: + if (errorstr == NULL) + errorstr = "Permission denied.\n"; + error(errorstr, errorhost); + exit(1); + } + + if (pwd->pw_uid && !access(_PATH_NOLOGIN, F_OK)) { + error("Logins currently disabled.\n"); + exit(1); + } + + (void) write(STDERR_FILENO, "\0", 1); + sent_null = 1; + + if (port) { + if (pipe(pv) < 0) { + error("Can't make pipe.\n"); + exit(1); + } +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + if (pipe(pv1) < 0) { + error("Can't make 2nd pipe.\n"); + exit(1); + } + if (pipe(pv2) < 0) { + error("Can't make 3rd pipe.\n"); + exit(1); + } + } +#endif +#endif + pid = fork(); + if (pid == -1) { + error("Can't fork; try again.\n"); + exit(1); + } + if (pid) { +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + static char msg[] = SECURE_MESSAGE; + (void) close(pv1[1]); + (void) close(pv2[1]); + des_write(s, msg, sizeof(msg) - 1); + + } else +#endif +#endif + { + (void) close(0); + (void) close(1); + } + (void) close(2); + (void) close(pv[1]); + + FD_ZERO(&readfrom); + FD_SET(s, &readfrom); + FD_SET(pv[0], &readfrom); + if (pv[0] > s) + nfd = pv[0]; + else + nfd = s; +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + FD_ZERO(&writeto); + FD_SET(pv2[0], &writeto); + FD_SET(pv1[0], &readfrom); + + nfd = MAX(nfd, pv2[0]); + nfd = MAX(nfd, pv1[0]); + } else +#endif +#endif + ioctl(pv[0], FIONBIO, (char *)&one); + + /* should set s nbio! */ + nfd++; + do { + ready = readfrom; +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + wready = writeto; + if (select(nfd, &ready, + &wready, (fd_set *) 0, + (struct timeval *) 0) < 0) + break; + } else +#endif +#endif + if (select(nfd, &ready, (fd_set *)0, + (fd_set *)0, (struct timeval *)0) < 0) + break; + if (FD_ISSET(s, &ready)) { + int ret; +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + ret = des_read(s, &sig, 1); + else +#endif +#endif + ret = read(s, &sig, 1); + if (ret <= 0) + FD_CLR(s, &readfrom); + else + killpg(pid, sig); + } + if (FD_ISSET(pv[0], &ready)) { + errno = 0; + cc = read(pv[0], buf, sizeof(buf)); + if (cc <= 0) { + shutdown(s, 1+1); + FD_CLR(pv[0], &readfrom); + } else { +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) + (void) + des_write(s, buf, cc); + else +#endif +#endif + (void) + write(s, buf, cc); + } + } +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt && FD_ISSET(pv1[0], &ready)) { + errno = 0; + cc = read(pv1[0], buf, sizeof(buf)); + if (cc <= 0) { + shutdown(pv1[0], 1+1); + FD_CLR(pv1[0], &readfrom); + } else + (void) des_write(STDOUT_FILENO, + buf, cc); + } + + if (doencrypt && FD_ISSET(pv2[0], &wready)) { + errno = 0; + cc = des_read(STDIN_FILENO, + buf, sizeof(buf)); + if (cc <= 0) { + shutdown(pv2[0], 1+1); + FD_CLR(pv2[0], &writeto); + } else + (void) write(pv2[0], buf, cc); + } +#endif +#endif + + } while (FD_ISSET(s, &readfrom) || +#ifdef CRYPT +#ifdef KERBEROS + (doencrypt && FD_ISSET(pv1[0], &readfrom)) || +#endif +#endif + FD_ISSET(pv[0], &readfrom)); + exit(0); + } + setpgrp(0, getpid()); + (void) close(s); + (void) close(pv[0]); +#ifdef CRYPT +#ifdef KERBEROS + if (doencrypt) { + close(pv1[0]); close(pv2[0]); + dup2(pv1[1], 1); + dup2(pv2[1], 0); + close(pv1[1]); + close(pv2[1]); + } +#endif +#endif + dup2(pv[1], 2); + close(pv[1]); + } + if (*pwd->pw_shell == '\0') + pwd->pw_shell = _PATH_BSHELL; +#if BSD > 43 + if (setlogin(pwd->pw_name) < 0) + syslog(LOG_ERR, "setlogin() failed: %m"); +#endif + (void) setgid((gid_t)pwd->pw_gid); + initgroups(pwd->pw_name, pwd->pw_gid); + (void) setuid((uid_t)pwd->pw_uid); + environ = envinit; + strncat(homedir, pwd->pw_dir, sizeof(homedir)-6); + strcat(path, _PATH_DEFPATH); + strncat(shell, pwd->pw_shell, sizeof(shell)-7); + strncat(username, pwd->pw_name, sizeof(username)-6); + cp = strrchr(pwd->pw_shell, '/'); + if (cp) + cp++; + else + cp = pwd->pw_shell; + endpwent(); + if (log_success || pwd->pw_uid == 0) { +#ifdef KERBEROS + if (use_kerberos) + syslog(LOG_INFO|LOG_AUTH, + "Kerberos shell from %s.%s@%s on %s as %s, cmd='%.80s'", + kdata->pname, kdata->pinst, kdata->prealm, + hostname, locuser, cmdbuf); + else +#endif + syslog(LOG_INFO|LOG_AUTH, "%s@%s as %s: cmd='%.80s'", + remuser, hostname, locuser, cmdbuf); + } + execl(pwd->pw_shell, cp, "-c", cmdbuf, 0); + perror(pwd->pw_shell); + exit(1); +} + +/* + * Report error to client. Note: can't be used until second socket has + * connected to client, or older clients will hang waiting for that + * connection first. + */ +#if __STDC__ +#include +#else +#include +#endif + +void +#if __STDC__ +error(const char *fmt, ...) +#else +error(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + int len; + char *bp, buf[BUFSIZ]; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + bp = buf; + if (sent_null == 0) { + *bp++ = 1; + len = 1; + } else + len = 0; + (void)vsnprintf(bp, sizeof(buf) - 1, fmt, ap); + (void)write(STDERR_FILENO, buf, len + strlen(bp)); +} + +void +getstr(buf, cnt, err) + char *buf, *err; + int cnt; +{ + char c; + + do { + if (read(STDIN_FILENO, &c, 1) != 1) + exit(1); + *buf++ = c; + if (--cnt == 0) { + error("%s too long\n", err); + exit(1); + } + } while (c != 0); +} + +/* + * Check whether host h is in our local domain, + * defined as sharing the last two components of the domain part, + * or the entire domain part if the local domain has only one component. + * If either name is unqualified (contains no '.'), + * assume that the host is local, as it will be + * interpreted as such. + */ +int +local_domain(h) + char *h; +{ + char localhost[MAXHOSTNAMELEN]; + char *p1, *p2; + + localhost[0] = 0; + (void) gethostname(localhost, sizeof(localhost)); + p1 = topdomain(localhost); + p2 = topdomain(h); + if (p1 == NULL || p2 == NULL || !strcasecmp(p1, p2)) + return (1); + return (0); +} + +char * +topdomain(h) + char *h; +{ + char *p, *maybe = NULL; + int dots = 0; + + for (p = h + strlen(h); p >= h; p--) { + if (*p == '.') { + if (++dots == 2) + return (p); + maybe = p; + } + } + return (maybe); +} + +void +usage() +{ + + syslog(LOG_ERR, "usage: rshd [-%s]", OPTIONS); + exit(2); +} diff --git a/ruptime.tproj/Makefile b/ruptime.tproj/Makefile new file mode 100644 index 0000000..09c2040 --- /dev/null +++ b/ruptime.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ruptime + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ruptime.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ + h.template ruptime.1 Makefile.dist + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ruptime.tproj/Makefile.dist b/ruptime.tproj/Makefile.dist new file mode 100644 index 0000000..57f1e15 --- /dev/null +++ b/ruptime.tproj/Makefile.dist @@ -0,0 +1,5 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= ruptime + +.include diff --git a/ruptime.tproj/Makefile.postamble b/ruptime.tproj/Makefile.postamble new file mode 100644 index 0000000..7823726 --- /dev/null +++ b/ruptime.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/ruptime.tproj/Makefile.preamble b/ruptime.tproj/Makefile.preamble new file mode 100644 index 0000000..74ce95a --- /dev/null +++ b/ruptime.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/ruptime.tproj/PB.project b/ruptime.tproj/PB.project new file mode 100644 index 0000000..f086f24 --- /dev/null +++ b/ruptime.tproj/PB.project @@ -0,0 +1,35 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (ruptime.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + m.template, + h.template, + ruptime.1, + Makefile.dist + ); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ruptime; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ruptime.tproj/h.template b/ruptime.tproj/h.template new file mode 100644 index 0000000..f3c1b04 --- /dev/null +++ b/ruptime.tproj/h.template @@ -0,0 +1,11 @@ +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import + +@interface $FILENAMESANSEXTENSION$ : NSObject +{ + +} + +@end diff --git a/ruptime.tproj/m.template b/ruptime.tproj/m.template new file mode 100644 index 0000000..1216fe5 --- /dev/null +++ b/ruptime.tproj/m.template @@ -0,0 +1,18 @@ +$$ Lines starting with $$ are not inserted into newly created files +$$ The following substitutions are made: +$$ +$$ $FILENAME$ e.g. foo.m +$$ $FILENAMESANSEXTENSION$ e.g. foo +$$ $DIRECTORY$ e.g. /tmp/MyNewApp +$$ $PROJECTNAME$ e.g. MyNewApp +$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj +$$ $USERNAME$ e.g. mwagner +$$ $DATE$ e.g. Jan-1-1994 +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import "$FILENAMESANSEXTENSION$.h" + +@implementation $FILENAMESANSEXTENSION$ + +@end diff --git a/ruptime.tproj/ruptime.1 b/ruptime.tproj/ruptime.1 new file mode 100644 index 0000000..b3b0af8 --- /dev/null +++ b/ruptime.tproj/ruptime.1 @@ -0,0 +1,81 @@ +.\" Copyright (c) 1983, 1990, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ruptime.1 8.2 (Berkeley) 4/5/94 +.\" +.Dd April 5, 1994 +.Dt RUPTIME 1 +.Os BSD 4.2 +.Sh NAME +.Nm ruptime +.Nd show host status of local machines +.Sh SYNOPSIS +.Nm ruptime +.Op Fl alrtu +.Sh DESCRIPTION +.Nm Ruptime +gives a status line like +.Ar uptime +for each machine on the local network; these are formed from packets +broadcast by each host on the network once a minute. +.Pp +Machines for which no status report has been received for 11 +minutes are shown as being down. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl a +Users idle an hour or more are not counted unless the +.Fl a +flag is given. +.It Fl l +Sort by load average. +.It Fl r +Reverses the sort order. +.It Fl t +Sort by uptime. +.It Fl u +Sort by number of users. +.El +.Pp +The default listing is sorted by host name. +.Sh FILES +.Bl -tag -width /var/rwho/whod.* -compact +.It Pa /var/rwho/whod.* +data files +.El +.Sh SEE ALSO +.Xr rwho 1 +.Xr uptime 1 +.Sh HISTORY +.Nm Ruptime +appeared in +.Bx 4.2 . diff --git a/ruptime.tproj/ruptime.c b/ruptime.tproj/ruptime.c new file mode 100644 index 0000000..e6cb457 --- /dev/null +++ b/ruptime.tproj/ruptime.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct hs { + struct whod *hs_wd; + int hs_nusers; +} *hs; +struct whod awhod; + +#define ISDOWN(h) (now - (h)->hs_wd->wd_recvtime > 11 * 60) +#define WHDRSIZE (sizeof (awhod) - sizeof (awhod.wd_we)) + +size_t nhosts; +time_t now; +int rflg = 1; + +int hscmp __P((const void *, const void *)); +char *interval __P((time_t, char *)); +int lcmp __P((const void *, const void *)); +void morehosts __P((void)); +int tcmp __P((const void *, const void *)); +int ucmp __P((const void *, const void *)); +void usage __P((void)); + +int +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + struct dirent *dp; + struct hs *hsp; + struct whod *wd; + struct whoent *we; + DIR *dirp; + size_t hspace; + int aflg, cc, ch, fd, i, maxloadav; + char buf[sizeof(struct whod)]; + int (*cmp) __P((const void *, const void *)); + + aflg = 0; + cmp = hscmp; + while ((ch = getopt(argc, argv, "alrut")) != EOF) + switch (ch) { + case 'a': + aflg = 1; + break; + case 'l': + cmp = lcmp; + break; + case 'r': + rflg = -1; + break; + case 't': + cmp = tcmp; + break; + case 'u': + cmp = ucmp; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 0) + usage(); + + if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) + err(1, "%s", _PATH_RWHODIR); + + maxloadav = -1; + for (nhosts = hspace = 0; (dp = readdir(dirp)) != NULL;) { + if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) + continue; + if ((fd = open(dp->d_name, O_RDONLY, 0)) < 0) { + warn("%s", dp->d_name); + continue; + } + cc = read(fd, buf, sizeof(struct whod)); + (void)close(fd); + + if (cc < WHDRSIZE) + continue; + if (nhosts == hspace) { + if ((hs = + realloc(hs, (hspace += 40) * sizeof(*hs))) == NULL) + err(1, NULL); + hsp = hs + nhosts; + } + + if ((hsp->hs_wd = malloc((size_t)WHDRSIZE)) == NULL) + err(1, NULL); + memmove(hsp->hs_wd, buf, (size_t)WHDRSIZE); + + for (wd = (struct whod *)buf, i = 0; i < 2; ++i) + if (wd->wd_loadav[i] > maxloadav) + maxloadav = wd->wd_loadav[i]; + + for (hsp->hs_nusers = 0, + we = (struct whoent *)(buf + cc); --we >= wd->wd_we;) + if (aflg || we->we_idle < 3600) + ++hsp->hs_nusers; + ++hsp; + ++nhosts; + } + if (nhosts == 0) + errx(0, "no hosts in %s.", _PATH_RWHODIR); + + (void)time(&now); + qsort(hs, nhosts, sizeof(hs[0]), cmp); + for (i = 0; i < nhosts; i++) { + hsp = &hs[i]; + if (ISDOWN(hsp)) { + (void)printf("%-12.12s%s\n", hsp->hs_wd->wd_hostname, + interval(now - hsp->hs_wd->wd_recvtime, "down")); + continue; + } + (void)printf( + "%-12.12s%s, %4d user%s load %*.2f, %*.2f, %*.2f\n", + hsp->hs_wd->wd_hostname, + interval((time_t)hsp->hs_wd->wd_sendtime - + (time_t)hsp->hs_wd->wd_boottime, " up"), + hsp->hs_nusers, + hsp->hs_nusers == 1 ? ", " : "s,", + maxloadav >= 1000 ? 5 : 4, + hsp->hs_wd->wd_loadav[0] / 100.0, + maxloadav >= 1000 ? 5 : 4, + hsp->hs_wd->wd_loadav[1] / 100.0, + maxloadav >= 1000 ? 5 : 4, + hsp->hs_wd->wd_loadav[2] / 100.0); + } + exit(0); +} + +char * +interval(tval, updown) + time_t tval; + char *updown; +{ + static char resbuf[32]; + int days, hours, minutes; + + if (tval < 0 || tval > DAYSPERNYEAR * SECSPERDAY) { + (void)snprintf(resbuf, sizeof(resbuf), " %s ??:??", updown); + return (resbuf); + } + /* round to minutes. */ + minutes = (tval + (SECSPERMIN - 1)) / SECSPERMIN; + hours = minutes / MINSPERHOUR; + minutes %= MINSPERHOUR; + days = hours / HOURSPERDAY; + hours %= HOURSPERDAY; + if (days) + (void)snprintf(resbuf, sizeof(resbuf), + "%s %2d+%02d:%02d", updown, days, hours, minutes); + else + (void)snprintf(resbuf, sizeof(resbuf), + "%s %2d:%02d", updown, hours, minutes); + return (resbuf); +} + +#define HS(a) ((struct hs *)(a)) + +/* Alphabetical comparison. */ +int +hscmp(a1, a2) + const void *a1, *a2; +{ + return (rflg * + strcmp(HS(a1)->hs_wd->wd_hostname, HS(a2)->hs_wd->wd_hostname)); +} + +/* Load average comparison. */ +int +lcmp(a1, a2) + const void *a1, *a2; +{ + if (ISDOWN(HS(a1))) + if (ISDOWN(HS(a2))) + return (tcmp(a1, a2)); + else + return (rflg); + else if (ISDOWN(HS(a2))) + return (-rflg); + else + return (rflg * + (HS(a2)->hs_wd->wd_loadav[0] - HS(a1)->hs_wd->wd_loadav[0])); +} + +/* Number of users comparison. */ +int +ucmp(a1, a2) + const void *a1, *a2; +{ + if (ISDOWN(HS(a1))) + if (ISDOWN(HS(a2))) + return (tcmp(a1, a2)); + else + return (rflg); + else if (ISDOWN(HS(a2))) + return (-rflg); + else + return (rflg * (HS(a2)->hs_nusers - HS(a1)->hs_nusers)); +} + +/* Uptime comparison. */ +int +tcmp(a1, a2) + const void *a1, *a2; +{ + return (rflg * ( + (ISDOWN(HS(a2)) ? HS(a2)->hs_wd->wd_recvtime - now + : HS(a2)->hs_wd->wd_sendtime - HS(a2)->hs_wd->wd_boottime) + - + (ISDOWN(HS(a1)) ? HS(a1)->hs_wd->wd_recvtime - now + : HS(a1)->hs_wd->wd_sendtime - HS(a1)->hs_wd->wd_boottime) + )); +} + +void +usage() +{ + (void)fprintf(stderr, "usage: ruptime [-alrut]\n"); + exit(1); +} diff --git a/rwho.tproj/Makefile b/rwho.tproj/Makefile new file mode 100644 index 0000000..ac0d8cb --- /dev/null +++ b/rwho.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rwho + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = rwho.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rwho.1\ + Makefile.dist + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rwho.tproj/Makefile.dist b/rwho.tproj/Makefile.dist new file mode 100644 index 0000000..328aa38 --- /dev/null +++ b/rwho.tproj/Makefile.dist @@ -0,0 +1,5 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= rwho + +.include diff --git a/rwho.tproj/Makefile.postamble b/rwho.tproj/Makefile.postamble new file mode 100644 index 0000000..7823726 --- /dev/null +++ b/rwho.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/rwho.tproj/Makefile.preamble b/rwho.tproj/Makefile.preamble new file mode 100644 index 0000000..74ce95a --- /dev/null +++ b/rwho.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/rwho.tproj/PB.project b/rwho.tproj/PB.project new file mode 100644 index 0000000..8a18feb --- /dev/null +++ b/rwho.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (rwho.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rwho.1, Makefile.dist); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rwho; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rwho.tproj/rwho.1 b/rwho.tproj/rwho.1 new file mode 100644 index 0000000..f039b01 --- /dev/null +++ b/rwho.tproj/rwho.1 @@ -0,0 +1,80 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rwho.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt RWHO 1 +.Os BSD 4.2 +.Sh NAME +.Nm rwho +.Nd who is logged in on local machines +.Sh SYNOPSIS +.Nm rwho +.Op Fl a +.Sh DESCRIPTION +The +.Nm rwho +command produces output similar to +.Xr who , +but for all machines on the local network. +If no report has been +received from a machine for 5 minutes then +.Nm rwho +assumes the machine is down, and does not report users last known +to be logged into that machine. +.Pp +If a users hasn't typed to the system for a minute or more, then +.Nm rwho +reports this idle time. If a user hasn't typed to the system for +an hour or more, then +the user will be omitted from the output of +.Nm rwho +unless the +.Fl a +flag is given. +.Sh FILES +.Bl -tag -width /var/rwho/rhowd.* -compact +.It Pa /var/rwho/whod.* +information about other machines +.El +.Sh SEE ALSO +.Xr ruptime 1 , +.Xr rwhod 8 +.Sh HISTORY +The +.Nm rwho +command +appeared in +.Bx 4.3 . +.Sh BUGS +This is unwieldy when the number of machines +on the local net is large. diff --git a/rwho.tproj/rwho.c b/rwho.tproj/rwho.c new file mode 100644 index 0000000..815f13a --- /dev/null +++ b/rwho.tproj/rwho.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#include +#include +#include +#include +#include + +DIR *dirp; + +struct whod wd; +int utmpcmp(); +#define NUSERS 1000 +struct myutmp { + char myhost[MAXHOSTNAMELEN]; + int myidle; + struct outmp myutmp; +} myutmp[NUSERS]; +int nusers; + +#define WHDRSIZE (sizeof (wd) - sizeof (wd.wd_we)) +/* + * this macro should be shared with ruptime. + */ +#define down(w,now) ((now) - (w)->wd_recvtime > 11 * 60) + +char *ctime(), *strcpy(); +time_t now; +int aflg; + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + int ch; + struct direct *dp; + int cc, width; + register struct whod *w = &wd; + register struct whoent *we; + register struct myutmp *mp; + int f, n, i; + time_t time(); + + while ((ch = getopt(argc, argv, "a")) != EOF) + switch((char)ch) { + case 'a': + aflg = 1; + break; + case '?': + default: + fprintf(stderr, "usage: rwho [-a]\n"); + exit(1); + } + if (chdir(_PATH_RWHODIR) || (dirp = opendir(".")) == NULL) { + perror(_PATH_RWHODIR); + exit(1); + } + mp = myutmp; + (void)time(&now); + while (dp = readdir(dirp)) { + if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5)) + continue; + f = open(dp->d_name, O_RDONLY); + if (f < 0) + continue; + cc = read(f, (char *)&wd, sizeof (struct whod)); + if (cc < WHDRSIZE) { + (void) close(f); + continue; + } + if (down(w,now)) { + (void) close(f); + continue; + } + cc -= WHDRSIZE; + we = w->wd_we; + for (n = cc / sizeof (struct whoent); n > 0; n--) { + if (aflg == 0 && we->we_idle >= 60*60) { + we++; + continue; + } + if (nusers >= NUSERS) { + printf("too many users\n"); + exit(1); + } + mp->myutmp = we->we_utmp; mp->myidle = we->we_idle; + (void) strcpy(mp->myhost, w->wd_hostname); + nusers++; we++; mp++; + } + (void) close(f); + } + qsort((char *)myutmp, nusers, sizeof (struct myutmp), utmpcmp); + mp = myutmp; + width = 0; + for (i = 0; i < nusers; i++) { + int j = strlen(mp->myhost) + 1 + strlen(mp->myutmp.out_line); + if (j > width) + width = j; + mp++; + } + mp = myutmp; + for (i = 0; i < nusers; i++) { + char buf[BUFSIZ]; + (void)sprintf(buf, "%s:%s", mp->myhost, mp->myutmp.out_line); + printf("%-8.8s %-*s %.12s", + mp->myutmp.out_name, + width, + buf, + ctime((time_t *)&mp->myutmp.out_time)+4); + mp->myidle /= 60; + if (mp->myidle) { + if (aflg) { + if (mp->myidle >= 100*60) + mp->myidle = 100*60 - 1; + if (mp->myidle >= 60) + printf(" %2d", mp->myidle / 60); + else + printf(" "); + } else + printf(" "); + printf(":%02d", mp->myidle % 60); + } + printf("\n"); + mp++; + } + exit(0); +} + +utmpcmp(u1, u2) + struct myutmp *u1, *u2; +{ + int rc; + + rc = strncmp(u1->myutmp.out_name, u2->myutmp.out_name, 8); + if (rc) + return (rc); + rc = strncmp(u1->myhost, u2->myhost, 8); + if (rc) + return (rc); + return (strncmp(u1->myutmp.out_line, u2->myutmp.out_line, 8)); +} diff --git a/rwhod.tproj/Makefile b/rwhod.tproj/Makefile new file mode 100644 index 0000000..fc4f54b --- /dev/null +++ b/rwhod.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = rwhod + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = rwhod.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble rwhod.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/rwhod.tproj/Makefile.postamble b/rwhod.tproj/Makefile.postamble new file mode 100644 index 0000000..f5c79e2 --- /dev/null +++ b/rwhod.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/rwhod.tproj/Makefile.preamble b/rwhod.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/rwhod.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/rwhod.tproj/PB.project b/rwhod.tproj/PB.project new file mode 100644 index 0000000..9329dd8 --- /dev/null +++ b/rwhod.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (rwhod.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, rwhod.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = rwhod; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/rwhod.tproj/rwhod.8 b/rwhod.tproj/rwhod.8 new file mode 100644 index 0000000..4b8492e --- /dev/null +++ b/rwhod.tproj/rwhod.8 @@ -0,0 +1,146 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)rwhod.8 8.2 (Berkeley) 12/11/93 +.\" +.Dd December 11, 1993 +.Dt RWHOD 8 +.Os BSD 4.2 +.Sh NAME +.Nm rwhod +.Nd system status server +.Sh SYNOPSIS +.Nm rwhod +.Sh DESCRIPTION +.Nm Rwhod +is the server which maintains the database used by the +.Xr rwho 1 +and +.Xr ruptime 1 +programs. Its operation is predicated on the ability to +.Em broadcast +messages on a network. +.Pp +.Nm Rwhod +operates as both a producer and consumer of status information. +As a producer of information it periodically +queries the state of the system and constructs +status messages which are broadcast on a network. +As a consumer of information, it listens for other +.Nm rwhod +servers' status messages, validating them, then recording +them in a collection of files located in the directory +.Pa /var/rwho . +.Pp +The server transmits and receives messages at the port indicated +in the ``rwho'' service specification; see +.Xr services 5 . +The messages sent and received, are of the form: +.Bd -literal -offset indent +struct outmp { + char out_line[8]; /* tty name */ + char out_name[8]; /* user id */ + long out_time; /* time on */ +}; + +struct whod { + char wd_vers; + char wd_type; + char wd_fill[2]; + int wd_sendtime; + int wd_recvtime; + char wd_hostname[32]; + int wd_loadav[3]; + int wd_boottime; + struct whoent { + struct outmp we_utmp; + int we_idle; + } wd_we[1024 / sizeof (struct whoent)]; +}; +.Ed +.Pp +All fields are converted to network byte order prior to +transmission. The load averages are as calculated by the +.Xr w 1 +program, and represent load averages over the 5, 10, and 15 minute +intervals prior to a server's transmission; they are multiplied by 100 +for representation in an integer. The host name +included is that returned by the +.Xr gethostname 2 +system call, with any trailing domain name omitted. +The array at the end of the message contains information about +the users logged in to the sending machine. This information +includes the contents of the +.Xr utmp 5 +entry for each non-idle terminal line and a value indicating the +time in seconds since a character was last received on the terminal line. +.Pp +Messages received by the +.Xr rwho +server are discarded unless they originated at an +.Xr rwho +server's port. In addition, if the host's name, as specified +in the message, contains any unprintable +.Tn ASCII +characters, the +message is discarded. Valid messages received by +.Nm rwhod +are placed in files named +.Pa whod.hostname +in the directory +.Pa /var/rwho . +These files contain only the most recent message, in the +format described above. +.Pp +Status messages are generated approximately once every +3 minutes. +.Nm Rwhod +performs an +.Xr nlist 3 +on +.Pa /vmunix +every 30 minutes to guard against +the possibility that this file is not the system +image currently operating. +.Sh SEE ALSO +.Xr rwho 1 , +.Xr ruptime 1 +.Sh BUGS +There should be a way to relay status information between networks. +Status information should be sent only upon request rather than continuously. +People often interpret the server dying +or network communication failures +as a machine going down. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/rwhod.tproj/rwhod.c b/rwhod.tproj/rwhod.c new file mode 100644 index 0000000..6094340 --- /dev/null +++ b/rwhod.tproj/rwhod.c @@ -0,0 +1,562 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Alarm interval. Don't forget to change the down time check in ruptime + * if this is changed. + */ +#define AL_INTERVAL (3 * 60) + +char myname[MAXHOSTNAMELEN]; + +/* + * We communicate with each neighbor in a list constructed at the time we're + * started up. Neighbors are currently directly connected via a hardware + * interface. + */ +struct neighbor { + struct neighbor *n_next; + char *n_name; /* interface name */ + struct sockaddr *n_addr; /* who to send to */ + int n_addrlen; /* size of address */ + int n_flags; /* should forward?, interface flags */ +}; + +struct neighbor *neighbors; +struct whod mywd; +struct servent *sp; +int s, utmpf; + +#define WHDRSIZE (sizeof(mywd) - sizeof(mywd.wd_we)) + +int configure __P((int)); +void getboottime __P((int)); +void onalrm __P((int)); +void quit __P((char *)); +void rt_xaddrs __P((caddr_t, caddr_t, struct rt_addrinfo *)); +int verify __P((char *)); +#ifdef DEBUG +char *interval __P((int, char *)); +void Sendto __P((int, char *, int, int, char *, int)); +#define sendto Sendto +#endif + +int +main(argc, argv) + int argc; + char argv[]; +{ + struct sockaddr_in from; + struct stat st; + char path[64]; + int on = 1; + char *cp; + struct sockaddr_in sin; + + if (getuid()) { + fprintf(stderr, "rwhod: not super user\n"); + exit(1); + } + sp = getservbyname("who", "udp"); + if (sp == NULL) { + fprintf(stderr, "rwhod: udp/who: unknown service\n"); + exit(1); + } +#ifndef DEBUG + daemon(1, 0); +#endif + if (chdir(_PATH_RWHODIR) < 0) { + (void)fprintf(stderr, "rwhod: %s: %s\n", + _PATH_RWHODIR, strerror(errno)); + exit(1); + } + (void) signal(SIGHUP, getboottime); + openlog("rwhod", LOG_PID, LOG_DAEMON); + /* + * Establish host name as returned by system. + */ + if (gethostname(myname, sizeof(myname) - 1) < 0) { + syslog(LOG_ERR, "gethostname: %m"); + exit(1); + } + if ((cp = index(myname, '.')) != NULL) + *cp = '\0'; + strncpy(mywd.wd_hostname, myname, sizeof(myname) - 1); + utmpf = open(_PATH_UTMP, O_RDONLY|O_CREAT, 0644); + if (utmpf < 0) { + syslog(LOG_ERR, "%s: %m", _PATH_UTMP); + exit(1); + } + getboottime(0); + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "socket: %m"); + exit(1); + } + if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { + syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); + exit(1); + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = sp->s_port; + if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + syslog(LOG_ERR, "bind: %m"); + exit(1); + } + if (!configure(s)) + exit(1); + signal(SIGALRM, onalrm); + onalrm(0); + for (;;) { + struct whod wd; + int cc, whod, len = sizeof(from); + + cc = recvfrom(s, (char *)&wd, sizeof(struct whod), 0, + (struct sockaddr *)&from, &len); + if (cc <= 0) { + if (cc < 0 && errno != EINTR) + syslog(LOG_WARNING, "recv: %m"); + continue; + } + if (from.sin_port != sp->s_port) { + syslog(LOG_WARNING, "%d: bad from port", + ntohs(from.sin_port)); + continue; + } + if (wd.wd_vers != WHODVERSION) + continue; + if (wd.wd_type != WHODTYPE_STATUS) + continue; + if (!verify(wd.wd_hostname)) { + syslog(LOG_WARNING, "malformed host name from %x", + from.sin_addr); + continue; + } + (void) sprintf(path, "whod.%s", wd.wd_hostname); + /* + * Rather than truncating and growing the file each time, + * use ftruncate if size is less than previous size. + */ + whod = open(path, O_WRONLY | O_CREAT, 0644); + if (whod < 0) { + syslog(LOG_WARNING, "%s: %m", path); + continue; + } +#if ENDIAN != BIG_ENDIAN + { + int i, n = (cc - WHDRSIZE)/sizeof(struct whoent); + struct whoent *we; + + /* undo header byte swapping before writing to file */ + wd.wd_sendtime = ntohl(wd.wd_sendtime); + for (i = 0; i < 3; i++) + wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]); + wd.wd_boottime = ntohl(wd.wd_boottime); + we = wd.wd_we; + for (i = 0; i < n; i++) { + we->we_idle = ntohl(we->we_idle); + we->we_utmp.out_time = + ntohl(we->we_utmp.out_time); + we++; + } + } +#endif + (void) time((time_t *)&wd.wd_recvtime); + (void) write(whod, (char *)&wd, cc); + if (fstat(whod, &st) < 0 || st.st_size > cc) + ftruncate(whod, cc); + (void) close(whod); + } +} + +/* + * Check out host name for unprintables + * and other funnies before allowing a file + * to be created. Sorry, but blanks aren't allowed. + */ +int +verify(name) + register char *name; +{ + register int size = 0; + + while (*name) { + if (!isascii(*name) || !(isalnum(*name) || ispunct(*name))) + return (0); + name++, size++; + } + return (size > 0); +} + +int utmptime; +int utmpent; +int utmpsize = 0; +struct utmp *utmp; +int alarmcount; + +void +onalrm(signo) + int signo; +{ + register struct neighbor *np; + register struct whoent *we = mywd.wd_we, *wlast; + register int i; + struct stat stb; + double avenrun[3]; + time_t now; + int cc; + + now = time(NULL); + if (alarmcount % 10 == 0) + getboottime(0); + alarmcount++; + (void) fstat(utmpf, &stb); + if ((stb.st_mtime != utmptime) || (stb.st_size > utmpsize)) { + utmptime = stb.st_mtime; + if (stb.st_size > utmpsize) { + utmpsize = stb.st_size + 10 * sizeof(struct utmp); + if (utmp) + utmp = (struct utmp *)realloc(utmp, utmpsize); + else + utmp = (struct utmp *)malloc(utmpsize); + if (! utmp) { + fprintf(stderr, "rwhod: malloc failed\n"); + utmpsize = 0; + goto done; + } + } + (void) lseek(utmpf, (off_t)0, L_SET); + cc = read(utmpf, (char *)utmp, stb.st_size); + if (cc < 0) { + fprintf(stderr, "rwhod: %s: %s\n", + _PATH_UTMP, strerror(errno)); + goto done; + } + wlast = &mywd.wd_we[1024 / sizeof(struct whoent) - 1]; + utmpent = cc / sizeof(struct utmp); + for (i = 0; i < utmpent; i++) + if (utmp[i].ut_name[0]) { + memcpy(we->we_utmp.out_line, utmp[i].ut_line, + sizeof(utmp[i].ut_line)); + memcpy(we->we_utmp.out_name, utmp[i].ut_name, + sizeof(utmp[i].ut_name)); + we->we_utmp.out_time = htonl(utmp[i].ut_time); + if (we >= wlast) + break; + we++; + } + utmpent = we - mywd.wd_we; + } + + /* + * The test on utmpent looks silly---after all, if no one is + * logged on, why worry about efficiency?---but is useful on + * (e.g.) compute servers. + */ + if (utmpent && chdir(_PATH_DEV)) { + syslog(LOG_ERR, "chdir(%s): %m", _PATH_DEV); + exit(1); + } + we = mywd.wd_we; + for (i = 0; i < utmpent; i++) { + if (stat(we->we_utmp.out_line, &stb) >= 0) + we->we_idle = htonl(now - stb.st_atime); + we++; + } + (void)getloadavg(avenrun, sizeof(avenrun)/sizeof(avenrun[0])); + for (i = 0; i < 3; i++) + mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100)); + cc = (char *)we - (char *)&mywd; + mywd.wd_sendtime = htonl(time(0)); + mywd.wd_vers = WHODVERSION; + mywd.wd_type = WHODTYPE_STATUS; + for (np = neighbors; np != NULL; np = np->n_next) + (void)sendto(s, (char *)&mywd, cc, 0, + np->n_addr, np->n_addrlen); + if (utmpent && chdir(_PATH_RWHODIR)) { + syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR); + exit(1); + } +done: + (void) alarm(AL_INTERVAL); +} + +void +getboottime(signo) + int signo; +{ + int mib[2]; + size_t size; + struct timeval tm; + + mib[0] = CTL_KERN; + mib[1] = KERN_BOOTTIME; + size = sizeof(tm); + if (sysctl(mib, 2, &tm, &size, NULL, 0) == -1) { + syslog(LOG_ERR, "cannot get boottime: %m"); + exit(1); + } + mywd.wd_boottime = htonl(tm.tv_sec); +} + +void +quit(msg) + char *msg; +{ + syslog(LOG_ERR, msg); + exit(1); +} + +#define ROUNDUP(a) \ + ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) +#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) + +void +rt_xaddrs(cp, cplim, rtinfo) + register caddr_t cp, cplim; + register struct rt_addrinfo *rtinfo; +{ + register struct sockaddr *sa; + register int i; + + memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); + for (i = 0; (i < RTAX_MAX) && (cp < cplim); i++) { + if ((rtinfo->rti_addrs & (1 << i)) == 0) + continue; + rtinfo->rti_info[i] = sa = (struct sockaddr *)cp; + ADVANCE(cp, sa); + } +} + +/* + * Figure out device configuration and select + * networks which deserve status information. + */ +int +configure(s) + int s; +{ + register struct neighbor *np; + register struct if_msghdr *ifm; + register struct ifa_msghdr *ifam; + struct sockaddr_dl *sdl; + size_t needed; + int mib[6], flags = 0, len; + char *buf, *lim, *next; + struct rt_addrinfo info; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = AF_INET; + mib[4] = NET_RT_IFLIST; + mib[5] = 0; + if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) + quit("route-sysctl-estimate"); + if ((buf = malloc(needed)) == NULL) + quit("malloc"); + if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) + quit("actual retrieval of interface table"); + lim = buf + needed; + + sdl = NULL; /* XXX just to keep gcc -Wall happy */ + for (next = buf; next < lim; next += ifm->ifm_msglen) { + ifm = (struct if_msghdr *)next; + if (ifm->ifm_type == RTM_IFINFO) { + sdl = (struct sockaddr_dl *)(ifm + 1); + flags = ifm->ifm_flags; + continue; + } + if ((flags & IFF_UP) == 0 || + (flags & (IFF_BROADCAST|IFF_POINTOPOINT)) == 0) + continue; + if (ifm->ifm_type != RTM_NEWADDR) + quit("out of sync parsing NET_RT_IFLIST"); + ifam = (struct ifa_msghdr *)ifm; + info.rti_addrs = ifam->ifam_addrs; + rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, + &info); + /* gag, wish we could get rid of Internet dependencies */ +#define dstaddr info.rti_info[RTAX_BRD] +#define IPADDR_SA(x) ((struct sockaddr_in *)(x))->sin_addr.s_addr +#define PORT_SA(x) ((struct sockaddr_in *)(x))->sin_port + if (dstaddr == 0 || dstaddr->sa_family != AF_INET) + continue; + PORT_SA(dstaddr) = sp->s_port; + for (np = neighbors; np != NULL; np = np->n_next) + if (memcmp(sdl->sdl_data, np->n_name, + sdl->sdl_nlen) == 0 && + IPADDR_SA(np->n_addr) == IPADDR_SA(dstaddr)) + break; + if (np != NULL) + continue; + len = sizeof(*np) + dstaddr->sa_len + sdl->sdl_nlen + 1; + np = (struct neighbor *)malloc(len); + if (np == NULL) + quit("malloc of neighbor structure"); + memset(np, 0, len); + np->n_flags = flags; + np->n_addr = (struct sockaddr *)(np + 1); + np->n_addrlen = dstaddr->sa_len; + np->n_name = np->n_addrlen + (char *)np->n_addr; + np->n_next = neighbors; + neighbors = np; + memcpy((char *)np->n_addr, (char *)dstaddr, np->n_addrlen); + memcpy(np->n_name, sdl->sdl_data, sdl->sdl_nlen); + } + free(buf); + return (1); +} + +#ifdef DEBUG +void +Sendto(s, buf, cc, flags, to, tolen) + int s; + char *buf; + int cc, flags; + char *to; + int tolen; +{ + register struct whod *w = (struct whod *)buf; + register struct whoent *we; + struct sockaddr_in *sin = (struct sockaddr_in *)to; + + printf("sendto %x.%d\n", ntohl(sin->sin_addr), ntohs(sin->sin_port)); + printf("hostname %s %s\n", w->wd_hostname, + interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), " up")); + printf("load %4.2f, %4.2f, %4.2f\n", + ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0, + ntohl(w->wd_loadav[2]) / 100.0); + cc -= WHDRSIZE; + for (we = w->wd_we, cc /= sizeof(struct whoent); cc > 0; cc--, we++) { + time_t t = ntohl(we->we_utmp.out_time); + printf("%-8.8s %s:%s %.12s", + we->we_utmp.out_name, + w->wd_hostname, we->we_utmp.out_line, + ctime(&t)+4); + we->we_idle = ntohl(we->we_idle) / 60; + if (we->we_idle) { + if (we->we_idle >= 100*60) + we->we_idle = 100*60 - 1; + if (we->we_idle >= 60) + printf(" %2d", we->we_idle / 60); + else + printf(" "); + printf(":%02d", we->we_idle % 60); + } + printf("\n"); + } +} + +char * +interval(time, updown) + int time; + char *updown; +{ + static char resbuf[32]; + int days, hours, minutes; + + if (time < 0 || time > 3*30*24*60*60) { + (void) sprintf(resbuf, " %s ??:??", updown); + return (resbuf); + } + minutes = (time + 59) / 60; /* round to minutes */ + hours = minutes / 60; minutes %= 60; + days = hours / 24; hours %= 24; + if (days) + (void) sprintf(resbuf, "%s %2d+%02d:%02d", + updown, days, hours, minutes); + else + (void) sprintf(resbuf, "%s %2d:%02d", + updown, hours, minutes); + return (resbuf); +} +#endif diff --git a/slattach.tproj/Makefile b/slattach.tproj/Makefile new file mode 100644 index 0000000..1f2fd2d --- /dev/null +++ b/slattach.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = slattach + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = slattach.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.dist slattach.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/slattach.tproj/Makefile.dist b/slattach.tproj/Makefile.dist new file mode 100644 index 0000000..0a1e759 --- /dev/null +++ b/slattach.tproj/Makefile.dist @@ -0,0 +1,7 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= slattach +MAN8= slattach.0 +MLINKS= slattach.8 slip.8 + +.include diff --git a/slattach.tproj/Makefile.preamble b/slattach.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/slattach.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/slattach.tproj/PB.project b/slattach.tproj/PB.project new file mode 100644 index 0000000..df7d482 --- /dev/null +++ b/slattach.tproj/PB.project @@ -0,0 +1,32 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (slattach.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, slattach.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = slattach; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = slattach; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = slattach; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = slattach; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/slattach.tproj/slattach.8 b/slattach.tproj/slattach.8 new file mode 100644 index 0000000..217c481 --- /dev/null +++ b/slattach.tproj/slattach.8 @@ -0,0 +1,90 @@ +.\" Copyright (c) 1986, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)slattach.8 8.2 (Berkeley) 4/1/94 +.\" +.Dd April 1, 1994 +.Dt SLATTACH 8 +.Os BSD 4.3 +.Sh NAME +.Nm slattach +.Nd attach serial lines as network interfaces +.Sh SYNOPSIS +.Nm Slattach +.Ar ttyname Op Ar baudrate +.Sh DESCRIPTION +.Nm Slattach +is used to assign a tty line to a network interface, +and to define the network source and destination addresses. +The following operands are supported by +.Nm slattach : +.Bl -tag -width Ar +.It Ar ttyname +Specifies the name of the tty device. +.Ar Ttyname +should be a string of the form +.Ql ttyXX , +or +.Ql /dev/ttyXX . +.It Ar baudrate +Specifies the speed of the connection. If not specified, the +default of 9600 is used. +.El +.Pp +Only the super-user may attach a network interface. +.Pp +To detach the interface, use +.Dq Li ifconfig interface-name down +after killing off the +.Nm slattach +process. +.Ar Interface-name +is the name that is shown by +.Xr netstat 1 +.Sh EXAMPLES +.Bd -literal -offset indent -compact +slattach ttyh8 +slattach /dev/tty01 4800 +.Ed +.Sh DIAGNOSTICS +Messages indicating the specified interface does not exit, the +requested address is unknown, the user is not privileged and +tried to alter an interface's configuration. +.Sh SEE ALSO +.Xr netstat 1 , +.Xr netintro 4 , +.Xr ifconfig 8 , +.Xr rc 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/slattach.tproj/slattach.c b/slattach.tproj/slattach.c new file mode 100644 index 0000000..580da18 --- /dev/null +++ b/slattach.tproj/slattach.c @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Adams. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_BAUD 9600 +int slipdisc = SLIPDISC; + +__private_extern__ +char devname[32] = { '\0' }; +char hostname[MAXHOSTNAMELEN]; + +main(argc, argv) + int argc; + char *argv[]; +{ + register int fd; + register char *dev = argv[1]; + struct sgttyb sgtty; + int speed; + + if (argc < 2 || argc > 3) { + fprintf(stderr, "usage: %s ttyname [baudrate]\n", argv[0]); + exit(1); + } + speed = argc == 3 ? findspeed(atoi(argv[2])) : findspeed(DEFAULT_BAUD); + if (speed == 0) { + fprintf(stderr, "unknown speed %s", argv[2]); + exit(1); + } + if (strncmp(_PATH_DEV, dev, sizeof(_PATH_DEV) - 1)) { + (void)snprintf(devname, sizeof(devname), + "%s%s", _PATH_DEV, dev); + dev = devname; + } + if ((fd = open(dev, O_RDWR | O_NDELAY)) < 0) { + perror(dev); + exit(1); + } + sgtty.sg_flags = RAW | ANYP; + sgtty.sg_ispeed = sgtty.sg_ospeed = speed; + if (ioctl(fd, TIOCSETP, &sgtty) < 0) { + perror("ioctl(TIOCSETP)"); + exit(1); + } + if (ioctl(fd, TIOCSETD, &slipdisc) < 0) { + perror("ioctl(TIOCSETD)"); + exit(1); + } + + if (fork() > 0) + exit(0); + for (;;) + sigpause(0L); +} + +struct sg_spds { + int sp_val, sp_name; +} spds[] = { +#ifdef B50 + { 50, B50 }, +#endif +#ifdef B75 + { 75, B75 }, +#endif +#ifdef B110 + { 110, B110 }, +#endif +#ifdef B150 + { 150, B150 }, +#endif +#ifdef B200 + { 200, B200 }, +#endif +#ifdef B300 + { 300, B300 }, +#endif +#ifdef B600 + { 600, B600 }, +#endif +#ifdef B1200 + { 1200, B1200 }, +#endif +#ifdef B1800 + { 1800, B1800 }, +#endif +#ifdef B2000 + { 2000, B2000 }, +#endif +#ifdef B2400 + { 2400, B2400 }, +#endif +#ifdef B3600 + { 3600, B3600 }, +#endif +#ifdef B4800 + { 4800, B4800 }, +#endif +#ifdef B7200 + { 7200, B7200 }, +#endif +#ifdef B9600 + { 9600, B9600 }, +#endif +#ifdef EXTA + { 19200, EXTA }, +#endif +#ifdef EXTB + { 38400, EXTB }, +#endif + { 0, 0 } +}; + +findspeed(speed) + register int speed; +{ + register struct sg_spds *sp; + + sp = spds; + while (sp->sp_val && sp->sp_val != speed) + sp++; + return (sp->sp_name); +} diff --git a/sliplogin.tproj/Makefile b/sliplogin.tproj/Makefile new file mode 100644 index 0000000..b106e74 --- /dev/null +++ b/sliplogin.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = sliplogin + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = pathnames.h + +CFILES = sliplogin.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble sliplogin.8\ + slip.hosts slip.login + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/sliplogin.tproj/Makefile.postamble b/sliplogin.tproj/Makefile.postamble new file mode 100644 index 0000000..de54c24 --- /dev/null +++ b/sliplogin.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +INSTALL_PERMISSIONS = 4555 # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/sliplogin.tproj/Makefile.preamble b/sliplogin.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/sliplogin.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/sliplogin.tproj/PB.project b/sliplogin.tproj/PB.project new file mode 100644 index 0000000..04d7107 --- /dev/null +++ b/sliplogin.tproj/PB.project @@ -0,0 +1,48 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (pathnames.h); + OTHER_LIBS = (); + OTHER_LINKED = (sliplogin.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + sliplogin.8, + slip.hosts, + slip.login + ); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = sliplogin; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/sliplogin.tproj/pathnames.h b/sliplogin.tproj/pathnames.h new file mode 100644 index 0000000..3060035 --- /dev/null +++ b/sliplogin.tproj/pathnames.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#ifndef COMPAT +#include +#else +#define _PATH_DEVNULL "/dev/null" +#endif + +#define _PATH_ACCESS "/etc/sliphome/slip.hosts" +#define _PATH_LOGIN "/etc/sliphome/slip.login" +#define _PATH_LOGOUT "/etc/sliphome/slip.logout" +#define _PATH_DEBUG "/tmp/sliplogin.XXXXXX" + diff --git a/sliplogin.tproj/slip.hosts b/sliplogin.tproj/slip.hosts new file mode 100644 index 0000000..f6ebf40 --- /dev/null +++ b/sliplogin.tproj/slip.hosts @@ -0,0 +1,11 @@ +# @(#)slip.hosts 8.1 (Berkeley) 6/6/93 +# +# login local-addr remote-addr mask opt1 opt2 +# (normal,compress,noicmp) +# +Schez vangogh chez 0xffffff00 compress +Sjun vangogh 128.32.130.36 0xffffff00 normal +Sleconte vangogh leconte 0xffffff00 compress +Sleeb vangogh leeb 0xffffff00 compress +Smjk vangogh pissaro-sl 0xffffff00 compress +Soxford vangogh oxford 0xffffff00 compress diff --git a/sliplogin.tproj/slip.login b/sliplogin.tproj/slip.login new file mode 100644 index 0000000..3c70095 --- /dev/null +++ b/sliplogin.tproj/slip.login @@ -0,0 +1,12 @@ +#!/bin/sh - +# +# @(#)slip.login 8.1 (Berkeley) 6/6/93 + +# +# generic login file for a slip line. sliplogin invokes this with +# the parameters: +# 1 2 3 4 5 6 7-n +# slipunit ttyspeed loginname local-addr remote-addr mask opt-args +# +/sbin/ifconfig sl$1 inet $4 $5 netmask $6 +exit diff --git a/sliplogin.tproj/sliplogin.8 b/sliplogin.tproj/sliplogin.8 new file mode 100644 index 0000000..1c71988 --- /dev/null +++ b/sliplogin.tproj/sliplogin.8 @@ -0,0 +1,220 @@ +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)sliplogin.8 8.2 (Berkeley) 1/5/94 +.\" +.Dd January 5, 1994 +.Dt SLIPLOGIN 8 +.Os +.Sh NAME +.Nm sliplogin +.Nd attach a serial line network interface +.Sh SYNOPSIS +.Nm sliplogin +.Op Ar loginname +.Sh DESCRIPTION +.Nm Sliplogin +is used to turn the terminal line on standard input into +a Serial Line IP +.Pq Tn SLIP +link to a remote host. To do this, the program +searches the file +.Pa /etc/sliphome/slip.hosts +for an entry matching +.Ar loginname +(which defaults to the current login name if omitted). +If a matching entry is found, the line is configured appropriately +for slip (8-bit transparent i/o) and converted to +.Tn SLIP +line +discipline. Then a shell script is invoked to initialize the slip +interface with the appropriate local and remote +.Tn IP +address, +netmask, etc. +.Pp +The usual initialization script is +.Pa /etc/sliphome/slip.login +but, if particular hosts need special initialization, the file +.Pa /etc/sliphome/slip.login. Ns Ar loginname +will be executed instead if it exists. +The script is invoked with the parameters +.Bl -tag -width slipunit +.It Em slipunit +The unit number of the slip interface assigned to this line. E.g., +.Sy 0 +for +.Sy sl0 . +.It Em speed +The speed of the line. +.It Em args +The arguments from the +.Pa /etc/sliphome/slip.hosts +entry, in order starting with +.Ar loginname . +.El +.Pp +Only the super-user may attach a network interface. The interface is +automatically detached when the other end hangs up or the +.Nm sliplogin +process dies. If the kernel slip +module has been configured for it, all routes through that interface will +also disappear at the same time. If there is other processing a site +would like done on hangup, the file +.Pa /etc/sliphome/slip.logout +or +.Pa /etc/sliphome/slip.logout. Ns Ar loginname +is executed if it exists. It is given the same arguments as the login script. +.Ss Format of /etc/sliphome/slip.hosts +Comments (lines starting with a `#') and blank lines are ignored. +Other lines must start with a +.Ar loginname +but the remaining arguments can be whatever is appropriate for the +.Pa slip.login +file that will be executed for that name. +Arguments are separated by white space and follow normal +.Xr sh 1 +quoting conventions (however, +.Ar loginname +cannot be quoted). +Usually, lines have the form +.Bd -literal -offset indent +loginname local-address remote-address netmask opt-args +.Ed +.Pp +where +.Em local-address +and +.Em remote-address +are the IP host names or addresses of the local and remote ends of the +slip line and +.Em netmask +is the appropriate IP netmask. These arguments are passed +directly to +.Xr ifconfig 8 . +.Em Opt-args +are optional arguments used to configure the line. +.Sh EXAMPLE +The normal use of +.Nm sliplogin +is to create a +.Pa /etc/passwd +entry for each legal, remote slip site with +.Nm sliplogin +as the shell for that entry. E.g., +.Bd -literal +Sfoo:ikhuy6:2010:1:slip line to foo:/tmp:/usr/sbin/sliplogin +.Ed +.Pp +(Our convention is to name the account used by remote host +.Ar hostname +as +.Em Shostname . ) +Then an entry is added to +.Pa slip.hosts +that looks like: +.Pp +.Bd -literal -offset indent -compact +Sfoo `hostname` foo netmask +.Ed +.Pp +where +.Em `hostname` +will be evaluated by +.Xr sh +to the local host name and +.Em netmask +is the local host IP netmask. +.Pp +Note that +.Nm sliplogin +must be setuid to root and, while not a security hole, moral defectives +can use it to place terminal lines in an unusable state and/or deny +access to legitimate users of a remote slip line. To prevent this, +a site can create a group, say +.Em slip , +that only the slip login accounts are put in then make sure that +.Pa /usr/sbin/sliplogin +is in group +.Em slip +and mode 4550 (setuid root, only group +.Em slip +can execute binary). +.Sh DIAGNOSTICS +.Nm Sliplogin +logs various information to the system log daemon, +.Xr syslogd 8 , +with a facility code of +.Em daemon . +The messages are listed here, grouped by severity level. +.Pp +.Sy Error Severity +.Bl -tag -width Ds -compact +.It Sy ioctl (TCGETS): Em reason +A +.Dv TCGETS +.Fn ioctl +to get the line parameters failed. +.Pp +.It Sy ioctl (TCSETS): Em reason +A +.Dv TCSETS +.Fn ioctl +to set the line parameters failed. +.Pp +.It Sy /etc/sliphome/slip.hosts: Em reason +The +.Pa /etc/sliphome/slip.hosts +file could not be opened. +.Pp +.It Sy access denied for Em user +No entry for +.Em user +was found in +.Pa /etc/sliphome/slip.hosts . +.El +.Pp +.Sy Notice Severity +.Bl -tag -width Ds -compact +.It Sy "attaching slip unit" Em unit Sy for Ar loginname +.Tn SLIP +unit +.Em unit +was successfully attached. +.El +.Sh SEE ALSO +.Xr slattach 8 , +.Xr syslogd 8 +.Sh HISTORY +The +.Nm +command +.Bt diff --git a/sliplogin.tproj/sliplogin.c b/sliplogin.tproj/sliplogin.c new file mode 100644 index 0000000..d1cdcab --- /dev/null +++ b/sliplogin.tproj/sliplogin.c @@ -0,0 +1,404 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)sliplogin.c 8.2 (Berkeley) 2/1/94"; +#endif /* not lint */ + +/* + * sliplogin.c + * [MUST BE RUN SUID, SLOPEN DOES A SUSER()!] + * + * This program initializes its own tty port to be an async TCP/IP interface. + * It sets the line discipline to slip, invokes a shell script to initialize + * the network interface, then pauses forever waiting for hangup. + * + * It is a remote descendant of several similar programs with incestuous ties: + * - Kirk Smith's slipconf, modified by Richard Johnsson @ DEC WRL. + * - slattach, probably by Rick Adams but touched by countless hordes. + * - the original sliplogin for 4.2bsd, Doug Kingston the mover behind it. + * + * There are two forms of usage: + * + * "sliplogin" + * Invoked simply as "sliplogin", the program looks up the username + * in the file /etc/slip.hosts. + * If an entry is found, the line on fd0 is configured for SLIP operation + * as specified in the file. + * + * "sliplogin IPhostlogin +#include +#include +#include +#include +#include + +#if BSD >= 199006 +#define POSIX +#endif +#ifdef POSIX +#include +#include +#include +#else +#include +#endif +#include + +#include +#include +#include +#include +#include "pathnames.h" + +int unit; +int speed; +int uid; +char loginargs[BUFSIZ]; +char loginfile[MAXPATHLEN]; +char loginname[BUFSIZ]; + +void +findid(name) + char *name; +{ + FILE *fp; + static char slopt[5][16]; + static char laddr[16]; + static char raddr[16]; + static char mask[16]; + char user[16]; + int i, j, n; + + (void)strcpy(loginname, name); + if ((fp = fopen(_PATH_ACCESS, "r")) == NULL) { + (void)fprintf(stderr, "sliplogin: %s: %s\n", + _PATH_ACCESS, strerror(errno)); + syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS); + exit(1); + } + while (fgets(loginargs, sizeof(loginargs) - 1, fp)) { + if (ferror(fp)) + break; + n = sscanf(loginargs, "%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s%*[ \t]%15s\n", + user, laddr, raddr, mask, slopt[0], slopt[1], + slopt[2], slopt[3], slopt[4]); + if (user[0] == '#' || isspace(user[0])) + continue; + if (strcmp(user, name) != 0) + continue; + + /* + * we've found the guy we're looking for -- see if + * there's a login file we can use. First check for + * one specific to this host. If none found, try for + * a generic one. + */ + (void)sprintf(loginfile, "%s.%s", _PATH_LOGIN, name); + if (access(loginfile, R_OK|X_OK) != 0) { + (void)strcpy(loginfile, _PATH_LOGIN); + if (access(loginfile, R_OK|X_OK)) { + fputs("access denied - no login file\n", + stderr); + syslog(LOG_ERR, + "access denied for %s - no %s\n", + name, _PATH_LOGIN); + exit(5); + } + } + + (void) fclose(fp); + return; + } + (void)fprintf(stderr, "SLIP access denied for %s\n", name); + syslog(LOG_ERR, "SLIP access denied for %s\n", name); + exit(4); + /* NOTREACHED */ +} + +char * +sigstr(s) + int s; +{ + static char buf[32]; + + switch (s) { + case SIGHUP: return("HUP"); + case SIGINT: return("INT"); + case SIGQUIT: return("QUIT"); + case SIGILL: return("ILL"); + case SIGTRAP: return("TRAP"); + case SIGIOT: return("IOT"); + case SIGEMT: return("EMT"); + case SIGFPE: return("FPE"); + case SIGKILL: return("KILL"); + case SIGBUS: return("BUS"); + case SIGSEGV: return("SEGV"); + case SIGSYS: return("SYS"); + case SIGPIPE: return("PIPE"); + case SIGALRM: return("ALRM"); + case SIGTERM: return("TERM"); + case SIGURG: return("URG"); + case SIGSTOP: return("STOP"); + case SIGTSTP: return("TSTP"); + case SIGCONT: return("CONT"); + case SIGCHLD: return("CHLD"); + case SIGTTIN: return("TTIN"); + case SIGTTOU: return("TTOU"); + case SIGIO: return("IO"); + case SIGXCPU: return("XCPU"); + case SIGXFSZ: return("XFSZ"); + case SIGVTALRM: return("VTALRM"); + case SIGPROF: return("PROF"); + case SIGWINCH: return("WINCH"); +#ifdef SIGLOST + case SIGLOST: return("LOST"); +#endif + case SIGUSR1: return("USR1"); + case SIGUSR2: return("USR2"); + } + (void)sprintf(buf, "sig %d", s); + return(buf); +} + +void +hup_handler(s) + int s; +{ + char logoutfile[MAXPATHLEN]; + + (void)sprintf(logoutfile, "%s.%s", _PATH_LOGOUT, loginname); + if (access(logoutfile, R_OK|X_OK) != 0) + (void)strcpy(logoutfile, _PATH_LOGOUT); + if (access(logoutfile, R_OK|X_OK) == 0) { + char logincmd[2*MAXPATHLEN+32]; + + (void) sprintf(logincmd, "%s %d %d %s", logoutfile, unit, speed, + loginargs); + (void) system(logincmd); + } + (void) close(0); + syslog(LOG_INFO, "closed %s slip unit %d (%s)\n", loginname, unit, + sigstr(s)); + exit(1); + /* NOTREACHED */ +} + +main(argc, argv) + int argc; + char *argv[]; +{ + int fd, s, ldisc, odisc; + char *name; +#ifdef POSIX + struct termios tios, otios; +#else + struct sgttyb tty, otty; +#endif + char logincmd[2*BUFSIZ+32]; + extern uid_t getuid(); + + if ((name = strrchr(argv[0], '/')) == NULL) + name = argv[0]; + s = getdtablesize(); + for (fd = 3 ; fd < s ; fd++) + (void) close(fd); + openlog(name, LOG_PID, LOG_DAEMON); + uid = getuid(); + if (argc > 1) { + findid(argv[1]); + + /* + * Disassociate from current controlling terminal, if any, + * and ensure that the slip line is our controlling terminal. + */ +#ifdef POSIX + if (fork() > 0) + exit(0); + if (setsid() != 0) + perror("setsid"); +#else + if ((fd = open("/dev/tty", O_RDONLY, 0)) >= 0) { + extern char *ttyname(); + + (void) ioctl(fd, TIOCNOTTY, (caddr_t)0); + (void) close(fd); + /* open slip tty again to acquire as controlling tty? */ + fd = open(ttyname(0), O_RDWR, 0); + if (fd >= 0) + (void) close(fd); + } + (void) setpgrp(0, getpid()); +#endif + if (argc > 2) { + if ((fd = open(argv[2], O_RDWR)) == -1) { + perror(argv[2]); + exit(2); + } + (void) dup2(fd, 0); + if (fd > 2) + close(fd); + } +#ifdef TIOCSCTTY + if (ioctl(0, TIOCSCTTY, (caddr_t)0) != 0) + perror("ioctl (TIOCSCTTY)"); +#endif + } else { + extern char *getlogin(); + + if ((name = getlogin()) == NULL) { + (void) fprintf(stderr, "access denied - no username\n"); + syslog(LOG_ERR, "access denied - getlogin returned 0\n"); + exit(1); + } + findid(name); + } + (void) fchmod(0, 0600); + (void) fprintf(stderr, "starting slip login for %s\n", loginname); +#ifdef POSIX + /* set up the line parameters */ + if (tcgetattr(0, &tios) < 0) { + syslog(LOG_ERR, "tcgetattr: %m"); + exit(1); + } + otios = tios; + cfmakeraw(&tios); + tios.c_iflag &= ~IMAXBEL; + if (tcsetattr(0, TCSAFLUSH, &tios) < 0) { + syslog(LOG_ERR, "tcsetattr: %m"); + exit(1); + } + speed = cfgetispeed(&tios); +#else + /* set up the line parameters */ + if (ioctl(0, TIOCGETP, (caddr_t)&tty) < 0) { + syslog(LOG_ERR, "ioctl (TIOCGETP): %m"); + exit(1); + } + otty = tty; + speed = tty.sg_ispeed; + tty.sg_flags = RAW | ANYP; + if (ioctl(0, TIOCSETP, (caddr_t)&tty) < 0) { + syslog(LOG_ERR, "ioctl (TIOCSETP): %m"); + exit(1); + } +#endif + /* find out what ldisc we started with */ + if (ioctl(0, TIOCGETD, (caddr_t)&odisc) < 0) { + syslog(LOG_ERR, "ioctl(TIOCGETD) (1): %m"); + exit(1); + } + ldisc = SLIPDISC; + if (ioctl(0, TIOCSETD, (caddr_t)&ldisc) < 0) { + syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + exit(1); + } + /* find out what unit number we were assigned */ + if (ioctl(0, SLIOCGUNIT, (caddr_t)&unit) < 0) { + syslog(LOG_ERR, "ioctl (SLIOCGUNIT): %m"); + exit(1); + } + (void) signal(SIGHUP, hup_handler); + (void) signal(SIGTERM, hup_handler); + + syslog(LOG_INFO, "attaching slip unit %d for %s\n", unit, loginname); + (void)sprintf(logincmd, "%s %d %d %s", loginfile, unit, speed, + loginargs); + /* + * aim stdout and errout at /dev/null so logincmd output won't + * babble into the slip tty line. + */ + (void) close(1); + if ((fd = open(_PATH_DEVNULL, O_WRONLY)) != 1) { + if (fd < 0) { + syslog(LOG_ERR, "open /dev/null: %m"); + exit(1); + } + (void) dup2(fd, 1); + (void) close(fd); + } + (void) dup2(1, 2); + + /* + * Run login and logout scripts as root (real and effective); + * current route(8) is setuid root, and checks the real uid + * to see whether changes are allowed (or just "route get"). + */ + (void) setuid(0); + if (s = system(logincmd)) { + syslog(LOG_ERR, "%s login failed: exit status %d from %s", + loginname, s, loginfile); + (void) ioctl(0, TIOCSETD, (caddr_t)&odisc); + exit(6); + } + + /* twiddle thumbs until we get a signal */ + while (1) + sigpause(0); + + /* NOTREACHED */ +} diff --git a/spray.tproj/Makefile b/spray.tproj/Makefile new file mode 100644 index 0000000..ad3c8d3 --- /dev/null +++ b/spray.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = spray + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = spray.c + +OTHERSRCS = Makefile Makefile.dist Makefile.postamble Makefile.preamble\ + spray.x + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/spray.tproj/Makefile.dist b/spray.tproj/Makefile.dist new file mode 100644 index 0000000..87c00aa --- /dev/null +++ b/spray.tproj/Makefile.dist @@ -0,0 +1,7 @@ +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:58:27 wsanchez Exp $ + +PROG= spray +NOMAN= +LDADD= -lrpcsvc + +.include diff --git a/spray.tproj/Makefile.postamble b/spray.tproj/Makefile.postamble new file mode 100644 index 0000000..6e5046f --- /dev/null +++ b/spray.tproj/Makefile.postamble @@ -0,0 +1,126 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. + +%_xdr.c: %.x + $(RPCGEN) $(ALL_RPCFLAGS) -c -o $(SYM_DIR)/$*_xdr.c $*.x + diff --git a/spray.tproj/Makefile.preamble b/spray.tproj/Makefile.preamble new file mode 100644 index 0000000..31db359 --- /dev/null +++ b/spray.tproj/Makefile.preamble @@ -0,0 +1,4 @@ +OTHER_OFILES = spray_xdr.o +OTHER_INITIAL_TARGETS = spray.h +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/spray.tproj/PB.project b/spray.tproj/PB.project new file mode 100644 index 0000000..72b61e4 --- /dev/null +++ b/spray.tproj/PB.project @@ -0,0 +1,37 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (spray.c); + OTHER_SOURCES = (Makefile, Makefile.dist, Makefile.postamble, Makefile.preamble, spray.x); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = spray; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/spray.tproj/spray.c b/spray.tproj/spray.c new file mode 100644 index 0000000..72d9c3e --- /dev/null +++ b/spray.tproj/spray.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993 Winning Strategies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Winning Strategies, Inc. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: spray.c,v 1.1.1.1 1999/05/02 03:58:27 wsanchez Exp $ + */ + +#include +#include +#include + +#include +#include + +#ifndef SPRAYOVERHEAD +#define SPRAYOVERHEAD 86 +#endif + +void usage (); +void print_xferstats (); + +/* spray buffer */ +char spray_buffer[SPRAYMAX]; + +/* RPC timeouts */ +struct timeval NO_DEFAULT = { -1, -1 }; +struct timeval ONE_WAY = { 0, 0 }; +struct timeval TIMEOUT = { 25, 0 }; + +int +main(argc, argv) + int argc; + char **argv; +{ + char *progname; + spraycumul host_stats; + sprayarr host_array; + CLIENT *cl; + int c; + int i; + int count = 0; + int delay = 0; + int length = 0; + double xmit_time; /* time to receive data */ + + progname = *argv; + while ((c = getopt(argc, argv, "c:d:l:")) != -1) { + switch (c) { + case 'c': + count = atoi(optarg); + break; + case 'd': + delay = atoi(optarg); + break; + case 'l': + length = atoi(optarg); + break; + default: + usage(); + /* NOTREACHED */ + } + } + argc -= optind; + argv += optind; + + if (argc != 1) { + usage(); + /* NOTREACHED */ + } + + + /* Correct packet length. */ + if (length > SPRAYMAX) { + length = SPRAYMAX; + } else if (length < SPRAYOVERHEAD) { + length = SPRAYOVERHEAD; + } else { + /* The RPC portion of the packet is a multiple of 32 bits. */ + length -= SPRAYOVERHEAD - 3; + length &= ~3; + length += SPRAYOVERHEAD; + } + + + /* + * The default value of count is the number of packets required + * to make the total stream size 100000 bytes. + */ + if (!count) { + count = 100000 / length; + } + + /* Initialize spray argument */ + host_array.sprayarr_len = length - SPRAYOVERHEAD; + host_array.sprayarr_val = spray_buffer; + + + /* create connection with server */ + cl = clnt_create(*argv, SPRAYPROG, SPRAYVERS, "udp"); + if (cl == NULL) { + clnt_pcreateerror(progname); + exit(1); + } + + + /* + * For some strange reason, RPC 4.0 sets the default timeout, + * thus timeouts specified in clnt_call() are always ignored. + * + * The following (undocumented) hack resets the internal state + * of the client handle. + */ + clnt_control(cl, CLSET_TIMEOUT, &NO_DEFAULT); + + + /* Clear server statistics */ + if (clnt_call(cl, SPRAYPROC_CLEAR, xdr_void, NULL, xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { + clnt_perror(cl, progname); + exit(1); + } + + + /* Spray server with packets */ + printf ("sending %d packets of lnth %d to %s ...", count, length, *argv); + fflush (stdout); + + for (i = 0; i < count; i++) { + clnt_call(cl, SPRAYPROC_SPRAY, xdr_sprayarr, &host_array, xdr_void, NULL, ONE_WAY); + + if (delay) { + usleep(delay); + } + } + + + /* Collect statistics from server */ + if (clnt_call(cl, SPRAYPROC_GET, xdr_void, NULL, xdr_spraycumul, &host_stats, TIMEOUT) != RPC_SUCCESS) { + clnt_perror(cl, progname); + exit(1); + } + + xmit_time = host_stats.clock.sec + + (host_stats.clock.usec / 1000000.0); + + printf ("\n\tin %.2f seconds elapsed time\n", xmit_time); + + + /* report dropped packets */ + if (host_stats.counter != count) { + int packets_dropped = count - host_stats.counter; + + printf("\t%d packets (%.2f%%) dropped\n", + packets_dropped, + 100.0 * packets_dropped / count ); + } else { + printf("\tno packets dropped\n"); + } + + printf("Sent:"); + print_xferstats(count, length, xmit_time); + + printf("Rcvd:"); + print_xferstats(host_stats.counter, length, xmit_time); + + exit (0); +} + + +void +print_xferstats(packets, packetlen, xfertime) + int packets; + int packetlen; + double xfertime; +{ + int datalen; + double pps; /* packets per second */ + double bps; /* bytes per second */ + + datalen = packets * packetlen; + pps = packets / xfertime; + bps = datalen / xfertime; + + printf("\t%.0f packets/sec, ", pps); + + if (bps >= 1024) + printf ("%.1fK ", bps / 1024); + else + printf ("%.0f ", bps); + + printf("bytes/sec\n"); +} + + +void +usage () +{ + fprintf(stderr, "usage: spray [-c count] [-l length] [-d delay] host\n"); + exit(1); +} diff --git a/spray.tproj/spray.x b/spray.tproj/spray.x new file mode 100644 index 0000000..5d2f883 --- /dev/null +++ b/spray.tproj/spray.x @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include diff --git a/startslip.tproj/Makefile b/startslip.tproj/Makefile new file mode 100644 index 0000000..968b995 --- /dev/null +++ b/startslip.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = startslip + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = startslip.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.dist startslip.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /sbin +WINDOWS_INSTALLDIR = /sbin +PDO_UNIX_INSTALLDIR = /sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/startslip.tproj/Makefile.dist b/startslip.tproj/Makefile.dist new file mode 100644 index 0000000..14c72bc --- /dev/null +++ b/startslip.tproj/Makefile.dist @@ -0,0 +1,6 @@ +# @(#)Makefile 8.1 (Berkeley) 6/5/93 + +PROG= startslip +MAN8= startslip.0 + +.include diff --git a/startslip.tproj/Makefile.preamble b/startslip.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/startslip.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/startslip.tproj/PB.project b/startslip.tproj/PB.project new file mode 100644 index 0000000..1ba4a2b --- /dev/null +++ b/startslip.tproj/PB.project @@ -0,0 +1,32 @@ +{ + APPCLASS = NSApplication; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (startslip.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.dist, startslip.1); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_INSTALLDIR = /sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_MAINNIB = startslip; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_MAINNIB = startslip; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = startslip; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_MAINNIB = startslip; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/startslip.tproj/startslip.1 b/startslip.tproj/startslip.1 new file mode 100644 index 0000000..f12feab --- /dev/null +++ b/startslip.tproj/startslip.1 @@ -0,0 +1,105 @@ +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)startslip.1 8.1 (Berkeley) 6/5/93 +.\" +.Dd June 5, 1993 +.Dt STARTSLIP 1 +.Os BSD 4.4 +.Sh NAME +.Nm startslip +.Nd dial up and login to a slip server +.Sh SYNOPSIS +.Nm startslip +.Op Fl d +.Op Fl s Ar string +.Op Fl A Ar annexname +.Op Fl F Ar flowcontrol +.Ar device user passwd +.Sh DESCRIPTION +.Nm Startslip +opens the specified +.Ar device . +.Pp +Once carrier is asserted +.Nm startslip +attempts to login as the specified +.Ar user +with the given +.Ar password . +If successful, it puts the device into the slip line discipline. +If carrier drops and a +.Dv SIGHUP +is sent to +.Nm startslip , +it closes the device and attempts to repeat the dialup and login sequence. +.Pp +Available options: +.Bl -tag -width Ar +.It Fl d +.Nm Startslip +prints out debugging information about what it is trying to do. +.It Fl s Ar string +The optional +.Ar string +is written to +.Ar device . +For a dialup modem, +the string is used to specify a dial sequence. +.It Fl A Ar annexname +.Nm Startslip +assumes it is connecting to a Xylogics Annex box and engages in an +appropriate dialog using the +.Ar user +and +.Ar passwd +arguments. +The +.Ar annexname +argument is a string that is used to match against the Annex prompt +to determine when a connection has been established. +.It Fl F Ar flowcontrol +Determines the type of flow control used on +.Ar device . +Choices for +.Ar flowcontrol +are +``none'' for no flow control (the default), +``hw'' for hardware RTS/CTS flow control and +``sw'' for software XON/XOFF flow control. +.El +.Sh SEE ALSO +.Xr sliplogin 8 +.Sh HISTORY +The +.Nm startslip +appeared in +.Bx 4.4 . diff --git a/startslip.tproj/startslip.c b/startslip.tproj/startslip.c new file mode 100644 index 0000000..f424137 --- /dev/null +++ b/startslip.tproj/startslip.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#if BSD >= 199006 +#define POSIX +#endif +#ifdef POSIX +#include +#include +#else +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEFAULT_BAUD B9600 +int speed = DEFAULT_BAUD; +#define FC_NONE 0 /* flow control: none */ +#define FC_SW 1 /* flow control: software (XON/XOFF) */ +#define FC_HW 2 /* flow control: hardware (RTS/CTS) */ +int flowcontrol = FC_NONE; +char *annex; +int hup; +int logged_in; +int wait_time = 60; /* then back off */ +#define MAXTRIES 6 /* w/60 sec and doubling, takes an hour */ +#define PIDFILE "/var/run/startslip.pid" + +#ifdef DEBUG +int debug = 1; +#undef LOG_ERR +#undef LOG_INFO +#define syslog fprintf +#define LOG_ERR stderr +#define LOG_INFO stderr +#else +int debug = 0; +#endif +#define printd if (debug) printf + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + char *cp, **ap; + int ch, disc; + int fd = -1; + void sighup(); + FILE *wfd = NULL, *pfd; + char *dialerstring = 0, buf[BUFSIZ]; + int first = 1, tries = 0; + int pausefirst = 0; + int pid; +#ifdef POSIX + struct termios t; +#else + struct sgttyb sgtty; +#endif + + while ((ch = getopt(argc, argv, "db:s:p:A:F:")) != EOF) + switch (ch) { + case 'd': + debug = 1; + break; +#ifdef POSIX + case 'b': + speed = atoi(optarg); + break; +#endif + case 'p': + pausefirst = atoi(optarg); + break; + case 's': + dialerstring = optarg; + break; + case 'A': + annex = optarg; + break; + case 'F': +#ifdef POSIX + if (strcmp(optarg, "none") == 0) + flowcontrol = FC_NONE; + else if (strcmp(optarg, "sw") == 0) + flowcontrol = FC_SW; + else if (strcmp(optarg, "hw") == 0) + flowcontrol = FC_HW; + else { + (void)fprintf(stderr, + "flow control: none, sw, hw\n"); + exit(1); + } + break; +#else + (void)fprintf(stderr, "flow control not supported\n"); + exit(1); +#endif + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 3) + usage(); + + openlog("startslip", LOG_PID, LOG_DAEMON); + +#if BSD <= 43 + if (debug == 0 && (fd = open("/dev/tty", 0)) >= 0) { + ioctl(fd, TIOCNOTTY, 0); + close(fd); + fd = -1; + } +#endif + + if (debug) + setbuf(stdout, NULL); + + if (pfd = fopen(PIDFILE, "r")) { + pid = 0; + fscanf(pfd, "%d", &pid); + if (pid > 0) + kill(pid, SIGUSR1); + fclose(pfd); + } +restart: + logged_in = 0; + if (++tries > MAXTRIES) { + syslog(LOG_ERR, "exiting after %d tries\n", tries); + /* ??? + if (first) + */ + exit(1); + } + + /* + * We may get a HUP below, when the parent (session leader/ + * controlling process) exits; ignore HUP until into new session. + */ + signal(SIGHUP, SIG_IGN); + hup = 0; + if (fork() > 0) { + if (pausefirst) + sleep(pausefirst); + if (first) + printd("parent exit\n"); + exit(0); + } + pausefirst = 0; +#ifdef POSIX + if (setsid() == -1) + perror("setsid"); +#endif + pid = getpid(); + printd("restart: pid %d: ", pid); + if (pfd = fopen(PIDFILE, "w")) { + fprintf(pfd, "%d\n", pid); + fclose(pfd); + } + if (wfd) { + printd("fclose, "); + fclose(wfd); + wfd == NULL; + } + if (fd >= 0) { + printd("close, "); + close(fd); + sleep(5); + } + printd("open"); + if ((fd = open(argv[0], O_RDWR)) < 0) { + perror(argv[0]); + syslog(LOG_ERR, "open %s: %m\n", argv[0]); + if (first) + exit(1); + else { + sleep(wait_time * tries); + goto restart; + } + } + printd(" %d", fd); +#ifdef TIOCSCTTY + if (ioctl(fd, TIOCSCTTY, 0) < 0) + perror("ioctl (TIOCSCTTY)"); +#endif + signal(SIGHUP, sighup); + if (debug) { + if (ioctl(fd, TIOCGETD, &disc) < 0) + perror("ioctl(TIOCSETD)"); + printf(" (disc was %d)", disc); + } + disc = TTYDISC; + if (ioctl(fd, TIOCSETD, &disc) < 0) { + perror("ioctl(TIOCSETD)"); + syslog(LOG_ERR, "%s: ioctl (TIOCSETD 0): %m\n", + argv[0]); + } + printd(", ioctl"); +#ifdef POSIX + if (tcgetattr(fd, &t) < 0) { + perror("tcgetattr"); + syslog(LOG_ERR, "%s: tcgetattr: %m\n", argv[0]); + exit(2); + } + cfmakeraw(&t); + t.c_iflag &= ~IMAXBEL; + switch (flowcontrol) { + case FC_HW: + t.c_cflag |= (CRTS_IFLOW|CCTS_OFLOW); + break; + case FC_SW: + t.c_iflag |= (IXON|IXOFF); + break; + case FC_NONE: + t.c_cflag &= ~(CRTS_IFLOW|CCTS_OFLOW); + t.c_iflag &= ~(IXON|IXOFF); + break; + } + cfsetspeed(&t, speed); + if (tcsetattr(fd, TCSAFLUSH, &t) < 0) { + perror("tcsetattr"); + syslog(LOG_ERR, "%s: tcsetattr: %m\n", argv[0]); + if (first) + exit(2); + else { + sleep(wait_time * tries); + goto restart; + } + } +#else + if (ioctl(fd, TIOCGETP, &sgtty) < 0) { + perror("ioctl (TIOCGETP)"); + syslog(LOG_ERR, "%s: ioctl (TIOCGETP): %m\n", + argv[0]); + exit(2); + } + sgtty.sg_flags = RAW | ANYP; + sgtty.sg_erase = sgtty.sg_kill = 0377; + sgtty.sg_ispeed = sgtty.sg_ospeed = speed; + if (ioctl(fd, TIOCSETP, &sgtty) < 0) { + perror("ioctl (TIOCSETP)"); + syslog(LOG_ERR, "%s: ioctl (TIOCSETP): %m\n", + argv[0]); + if (first) + exit(2); + else { + sleep(wait_time * tries); + goto restart; + } + } +#endif + sleep(2); /* wait for flakey line to settle */ + if (hup) + goto restart; + + wfd = fdopen(fd, "w+"); + if (wfd == NULL) { + syslog(LOG_ERR, "can't fdopen slip line\n"); + exit(10); + } + setbuf(wfd, (char *)0); + if (dialerstring) { + printd(", send dialstring"); + fprintf(wfd, "%s\r", dialerstring); + } else + putc('\r', wfd); + printd("\n"); + + /* + * Log in + */ + printd("look for login: "); + for (;;) { + if (getline(buf, BUFSIZ, fd) == 0 || hup) { + sleep(wait_time * tries); + goto restart; + } + if (annex) { + if (bcmp(buf, annex, strlen(annex)) == 0) { + fprintf(wfd, "slip\r"); + printd("Sent \"slip\"\n"); + continue; + } + if (bcmp(&buf[1], "sername:", 8) == 0) { + fprintf(wfd, "%s\r", argv[1]); + printd("Sent login: %s\n", argv[1]); + continue; + } + if (bcmp(&buf[1], "assword:", 8) == 0) { + fprintf(wfd, "%s\r", argv[2]); + printd("Sent password: %s\n", argv[2]); + break; + } + } else { + if (bcmp(&buf[1], "ogin:", 5) == 0) { + fprintf(wfd, "%s\r", argv[1]); + printd("Sent login: %s\n", argv[1]); + continue; + } + if (bcmp(&buf[1], "assword:", 8) == 0) { + fprintf(wfd, "%s\r", argv[2]); + printd("Sent password: %s\n", argv[2]); + break; + } + } + } + + /* + * Security hack. Do not want private information such as the + * password and possible phone number to be left around. + * So we clobber the arguments. + */ + for (ap = argv - optind + 1; ap < argv + 3; ap++) + for (cp = *ap; *cp != 0; cp++) + *cp = '\0'; + + /* + * Attach + */ + printd("setd"); + disc = SLIPDISC; + if (ioctl(fd, TIOCSETD, &disc) < 0) { + perror("ioctl(TIOCSETD)"); + syslog(LOG_ERR, "%s: ioctl (TIOCSETD SLIP): %m\n", + argv[0]); + exit(1); + } + if (first && debug == 0) { + close(0); + close(1); + close(2); + (void) open("/dev/null", O_RDWR); + (void) dup2(0, 1); + (void) dup2(0, 2); + } + (void) system("ifconfig sl0 up"); + printd(", ready\n"); + if (!first) + syslog(LOG_INFO, "reconnected (%d tries).\n", tries); + first = 0; + tries = 0; + logged_in = 1; + while (hup == 0) { + sigpause(0L); + printd("sigpause return\n"); + } + goto restart; +} + +void +sighup() +{ + + printd("hup\n"); + if (hup == 0 && logged_in) + syslog(LOG_INFO, "hangup signal\n"); + hup = 1; +} + +getline(buf, size, fd) + char *buf; + int size, fd; +{ + register int i; + int ret; + + size--; + for (i = 0; i < size; i++) { + if (hup) + return (0); + if ((ret = read(fd, &buf[i], 1)) == 1) { + buf[i] &= 0177; + if (buf[i] == '\r' || buf[i] == '\0') + buf[i] = '\n'; + if (buf[i] != '\n' && buf[i] != ':') + continue; + buf[i + 1] = '\0'; + printd("Got %d: \"%s\"\n", i + 1, buf); + return (i+1); + } + if (ret <= 0) { + if (ret < 0) + perror("getline: read"); + else + fprintf(stderr, "read returned 0\n"); + buf[i] = '\0'; + printd("returning 0 after %d: \"%s\"\n", i, buf); + return (0); + } + } + return (0); +} + +usage() +{ + (void)fprintf(stderr, + "usage: startslip [-d] [-b speed] [-s string] [-A annexname] [-F flowcontrol] dev user passwd\n"); + exit(1); +} diff --git a/stdethers.tproj/Makefile b/stdethers.tproj/Makefile new file mode 100644 index 0000000..3ee9c9a --- /dev/null +++ b/stdethers.tproj/Makefile @@ -0,0 +1,46 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = stdethers + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = stdethers.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble stdethers.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/stdethers.tproj/Makefile.postamble b/stdethers.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/stdethers.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/stdethers.tproj/Makefile.preamble b/stdethers.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/stdethers.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/stdethers.tproj/PB.project b/stdethers.tproj/PB.project new file mode 100644 index 0000000..6379be0 --- /dev/null +++ b/stdethers.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (stdethers.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, stdethers.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = stdethers; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/stdethers.tproj/stdethers.8 b/stdethers.tproj/stdethers.8 new file mode 100644 index 0000000..3740af7 --- /dev/null +++ b/stdethers.tproj/stdethers.8 @@ -0,0 +1,55 @@ +.\" $OpenBSD: stdethers.8,v 1.3 1996/05/30 09:53:11 deraadt Exp $ +.\" Copyright (c) 1995 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd December 2, 1995 +.Dt STDETHERS 8 +.Os +.Sh NAME +.Nm stdethers +.Nd a YP filter program +.Sh SYNOPSIS +.Nm stdethers +.Op Ar file +.Sh DESCRIPTION +.Nm Stdethers +is used to get ride of some unwanted information in file or stdin. This +program is used by YP when creating some YP maps. +.Pp +.Pp +The options are as follows: +.Bl -tag -width indent +.It Ar file +Use this file as input instead of stdin. +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr ypserv 8 +.Sh AUTHOR +Mats O Jansson diff --git a/stdethers.tproj/stdethers.c b/stdethers.tproj/stdethers.c new file mode 100644 index 0000000..f9ef339 --- /dev/null +++ b/stdethers.tproj/stdethers.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: stdethers.c,v 1.3 1997/09/11 19:47:33 deraadt Exp $ */ + +/* + * Copyright (c) 1995 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: stdethers.c,v 1.3 1997/09/11 19:47:33 deraadt Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +char *ProgramName = "stdethers"; + +extern int ether_line(char *, struct ether_addr *, char *); +extern char *ether_ntoa(struct ether_addr *); + +#ifndef NTOA_FIX +#define NTOA(x) (char *)ether_ntoa(x) +#else +#define NTOA(x) (char *) working_ntoa((u_char *) x) + +/* As of 1995-12-02 NetBSD and OpenBSD has an SunOS 4 incompatible ether_ntoa. + The code in usr/lib/libc/net/ethers seems to do the correct thing + when asking YP but not when returning string from ether_ntoa. + */ + +char * +working_ntoa(e) + u_char *e; +{ + static char a[] = "xx:xx:xx:xx:xx:xx"; + + sprintf(a, "%x:%x:%x:%x:%x:%x", + e[0], e[1], e[2], e[3], e[4], e[5]); + return a; +} +#endif + +static int read_line(fp, buf, size) +FILE *fp; +char *buf; +int size; +{ + int done = 0; + + do { + while (fgets(buf, size, fp)) { + int len = strlen(buf); + done += len; + if (len > 1 && buf[len-2] == '\\' && + buf[len-1] == '\n') { + int ch; + buf += len - 2; + size -= len - 2; + *buf = '\n'; buf[1] = '\0'; + /* + * Skip leading white space on next line + */ + while ((ch = getc(fp)) != EOF && + isascii(ch) && isspace(ch)) + ; + (void) ungetc(ch, fp); + } else { + return done; + } + } + } while (size > 0 && !feof(fp)); + + return done; +} + +int +main (argc,argv) +int argc; +char *argv[]; +{ + FILE *data_file; + char data_line[1024]; + int usage = 0; + int line_no = 0; + int len; + char *p,*k,*v; + struct ether_addr eth_addr; + char hostname[256]; + + if (argc > 2) { + usage++; + } + + if (usage) { + fprintf(stderr, + "usage: %s [file]\n", + ProgramName); + exit(1); + } + + if (argc == 2) { + data_file = fopen(argv[1], "r"); + if (data_file == NULL) { + fprintf(stderr, + "%s: can't open %s\n", + ProgramName, + argv[1]); + exit(1); + } + } else { + data_file = stdin; + } + + while (read_line(data_file,data_line,sizeof(data_line))) { + + line_no++; + len = strlen(data_line); + + if (len > 0) { + if (data_line[0] == '#') + continue; + } + + /* + * Check if we have the whole line + */ + + if (data_line[len-1] != '\n') { + if (argc == 2) { + fprintf(stderr, + "line %d in \"%s\" is too long", + line_no, argv[1]); + } else { + fprintf(stderr, + "line %d in \"stdin\" is too long", + line_no); + } + } else { + data_line[len-1] = '\0'; + } + + p = (char *) &data_line; + + k = p; /* save start of key */ + while (!isspace(*p)) { p++; }; /* find first "space" */ + while (isspace(*p)) { p++; }; /* move over "space" */ + + v = p; /* save start of value */ + while(*p != '\0') { p++; }; /* find end of string */ + + if (ether_line(data_line, ð_addr, hostname) == 0) { + fprintf(stdout, "%s\t%s\n", + NTOA(ð_addr), + hostname); + } else { + fprintf(stderr, + "%s: ignoring line %d: \"%s\"\n", + ProgramName, + line_no, + data_line); + } + } + + return(0); + +} diff --git a/stdhosts.tproj/Makefile b/stdhosts.tproj/Makefile new file mode 100644 index 0000000..600fddf --- /dev/null +++ b/stdhosts.tproj/Makefile @@ -0,0 +1,46 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = stdhosts + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = stdhosts.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble stdhosts.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/stdhosts.tproj/Makefile.postamble b/stdhosts.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/stdhosts.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/stdhosts.tproj/Makefile.preamble b/stdhosts.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/stdhosts.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/stdhosts.tproj/PB.project b/stdhosts.tproj/PB.project new file mode 100644 index 0000000..ba79c4b --- /dev/null +++ b/stdhosts.tproj/PB.project @@ -0,0 +1,26 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (stdhosts.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, stdhosts.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = stdhosts; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/stdhosts.tproj/stdhosts.8 b/stdhosts.tproj/stdhosts.8 new file mode 100644 index 0000000..6cd5540 --- /dev/null +++ b/stdhosts.tproj/stdhosts.8 @@ -0,0 +1,55 @@ +.\" $OpenBSD: stdhosts.8,v 1.4 1996/06/26 21:26:36 maja Exp $ +.\" Copyright (c) 1994 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd August 25, 1994 +.Dt STDHOSTS 8 +.Os +.Sh NAME +.Nm stdhosts +.Nd a YP filter program +.Sh SYNOPSIS +.Nm stdhosts +.Op Ar file +.Sh DESCRIPTION +.Nm Stdhosts +is used to get ride of some unwanted information in file or stdin. This +program is used by YP when creating some YP maps. +.Pp +.Pp +The options are as follows: +.Bl -tag -width indent +.It Ar file +Use this file as input instead of stdin. +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr ypserv 8 +.Sh AUTHOR +Mats O Jansson diff --git a/stdhosts.tproj/stdhosts.c b/stdhosts.tproj/stdhosts.c new file mode 100644 index 0000000..3406558 --- /dev/null +++ b/stdhosts.tproj/stdhosts.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: stdhosts.c,v 1.4 1997/09/11 19:47:35 deraadt Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: stdhosts.c,v 1.4 1997/09/11 19:47:35 deraadt Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include + +static int read_line(fp, buf, size) +FILE *fp; +char *buf; +int size; +{ + int done = 0; + + do { + while (fgets(buf, size, fp)) { + int len = strlen(buf); + done += len; + if (len > 1 && buf[len-2] == '\\' && + buf[len-1] == '\n') { + int ch; + buf += len - 2; + size -= len - 2; + *buf = '\n'; buf[1] = '\0'; + /* + * Skip leading white space on next line + */ + while ((ch = getc(fp)) != EOF && + isascii(ch) && isspace(ch)) + ; + (void) ungetc(ch, fp); + } else { + return done; + } + } + } while (size > 0 && !feof(fp)); + + return done; +} + +int +main (argc,argv) +int argc; +char *argv[]; +{ + FILE *data_file; + char data_line[1024]; + int usage = 0; + int line_no = 0; + int len; + char *p,*k,*v; + struct in_addr host_addr; + + if (argc > 2) { + usage++; + } + + if (usage) { + fprintf(stderr, + "%s", + "usage: stdhosts [file]\n"); + exit(1); + } + + if (argc == 2) { + data_file = fopen(argv[argc-1], "r"); + } else { + data_file = stdin; + } + + while (read_line(data_file,data_line,sizeof(data_line))) { + + line_no++; + len = strlen(data_line); + + if (len > 0) { + if (data_line[0] == '#') + continue; + } + + /* + * Check if we have the whole line + */ + + if (data_line[len-1] != '\n') { + if (argc == 2) { + fprintf(stderr, "line %d in \"%s\" is too long", line_no, argv[1]); + } else { + fprintf(stderr, "line %d in \"stdin\" is too long", line_no); + } + } else { + data_line[len-1] = '\0'; + } + + p = (char *) &data_line; + + k = p; /* save start of key */ + while (!isspace(*p)) { p++; }; /* find first "space" */ + while (isspace(*p)) { *p = '\0'; p++; }; /* replace space with */ + + v = p; /* save start of value */ + while(*p != '\0') { p++; }; /* find end of string */ + + (void)inet_aton(k,&host_addr); + printf("%s %s\n",inet_ntoa(host_addr),v); + + } + + return(0); + +} diff --git a/syslogd.tproj/Makefile b/syslogd.tproj/Makefile new file mode 100644 index 0000000..9eae816 --- /dev/null +++ b/syslogd.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = syslogd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = pathnames.h + +CFILES = syslogd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble syslogd.8\ + syslog.conf.5 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/syslogd.tproj/Makefile.postamble b/syslogd.tproj/Makefile.postamble new file mode 100644 index 0000000..60da20d --- /dev/null +++ b/syslogd.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. +VPATH += :../wall.tproj diff --git a/syslogd.tproj/Makefile.preamble b/syslogd.tproj/Makefile.preamble new file mode 100644 index 0000000..d2e854c --- /dev/null +++ b/syslogd.tproj/Makefile.preamble @@ -0,0 +1,115 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. + +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +OTHER_OFILES = ttymsg.o + +-include ../Makefile.include diff --git a/syslogd.tproj/PB.project b/syslogd.tproj/PB.project new file mode 100644 index 0000000..45a56f3 --- /dev/null +++ b/syslogd.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (pathnames.h); + OTHER_LIBS = (); + OTHER_LINKED = (syslogd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, syslogd.8, syslog.conf.5); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = syslogd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/syslogd.tproj/pathnames.h b/syslogd.tproj/pathnames.h new file mode 100644 index 0000000..b03e65d --- /dev/null +++ b/syslogd.tproj/pathnames.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +#define _PATH_KLOG "/dev/klog" +#define _PATH_LOGCONF "/etc/syslog.conf" +#define _PATH_LOGPID "/var/run/syslog.pid" diff --git a/syslogd.tproj/syslog.conf.5 b/syslogd.tproj/syslog.conf.5 new file mode 100644 index 0000000..b19e75d --- /dev/null +++ b/syslogd.tproj/syslog.conf.5 @@ -0,0 +1,224 @@ +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93 +.\" +.Dd June 9, 1993 +.Dt SYSLOG.CONF 5 +.Os +.Sh NAME +.Nm syslog.conf +.Nd +.Xr syslogd 8 +configuration file +.Sh DESCRIPTION +The +.Nm syslog.conf +file is the configuration file for the +.Xr syslogd 8 +program. +It consists of lines with two fields: the +.Em selector +field which specifies the types of messages and priorities to which the +line applies, and an +.Em action +field which specifies the action to be taken if a message +.Xr syslogd +receives matches the selection criteria. +The +.Em selector +field is separated from the +.Em action +field by one or more tab characters. +.Pp +The +.Em Selectors +function +are encoded as a +.Em facility , +a period (``.''), and a +.Em level , +with no intervening white-space. +Both the +.Em facility +and the +.Em level +are case insensitive. +.Pp +The +.Em facility +describes the part of the system generating the message, and is one of +the following keywords: auth, authpriv, cron, daemon, kern, lpr, mail, +mark, news, syslog, user, uucp and local0 through local7. +These keywords (with the exception of mark) correspond to the +similar +.Dq Dv LOG_ +values specified to the +.Xr openlog 3 +and +.Xr syslog 3 +library routines. +.Pp +The +.Em level +describes the severity of the message, and is a keyword from the +following ordered list (higher to lower): emerg, alert, crit, err, +warning, notice and debug. +These keywords correspond to the +similar +.Pq Dv LOG_ +values specified to the +.Xr syslog +library routine. +.Pp +See +.Xr syslog 3 +for a further descriptions of both the +.Em facility +and +.Em level +keywords and their significance. +.Pp +If a received message matches the specified +.Em facility +and is of the specified +.Em level +.Em (or a higher level) , +the action specified in the +.Em action +field will be taken. +.Pp +Multiple +.Em selectors +may be specified for a single +.Em action +by separating them with semicolon (``;'') characters. +It is important to note, however, that each +.Em selector +can modify the ones preceding it. +.Pp +Multiple +.Em facilities +may be specified for a single +.Em level +by separating them with comma (``,'') characters. +.Pp +An asterisk (``*'') can be used to specify all +.Em facilities +or all +.Em levels . +.Pp +The special +.Em facility +``mark'' receives a message at priority ``info'' every 20 minutes +(see +.Xr syslogd 8 ) . +This is not enabled by a +.Em facility +field containing an asterisk. +.Pp +The special +.Em level +``none'' disables a particular +.Em facility . +.Pp +The +.Em action +field of each line specifies the action to be taken when the +.Em selector +field selects a message. +There are four forms: +.Bl -bullet +.It +A pathname (beginning with a leading slash). +Selected messages are appended to the file. +.It +A hostname (preceded by an at (``@'') sign). +Selected messages are forwarded to the +.Xr syslogd +program on the named host. +.It +A comma separated list of users. +Selected messages are written to those users +if they are logged in. +.It +An asterisk. +Selected messages are written to all logged-in users. +.El +.Pp +Blank lines and lines whose first non-blank character is a hash (``#'') +character are ignored. +.Sh EXAMPLES +.Pp +A configuration file might appear as follows: +.Bd -literal +# Log all kernel messages, authentication messages of +# level notice or higher and anything of level err or +# higher to the console. +# Don't log private authentication messages! +*.err;kern.*;auth.notice;authpriv.none /dev/console + +# Log anything (except mail) of level info or higher. +# Don't log private authentication messages! +*.info;mail.none;authpriv.none /var/log/messages + +# The authpriv file has restricted access. +authpriv.* /var/log/secure + +# Log all the mail messages in one place. +mail.* /var/log/maillog + +# Everybody gets emergency messages, plus log them on another +# machine. +*.emerg * +*.emerg @arpa.berkeley.edu + +# Root and Eric get alert and higher messages. +*.alert root,eric + +# Save mail and news errors of level err and higher in a +# special file. +uucp,news.crit /var/log/spoolerr +.Ed +.Sh FILES +.Bl -tag -width /etc/syslog.conf -compact +.It Pa /etc/syslog.conf +The +.Xr syslogd 8 +configuration file. +.El +.Sh BUGS +The effects of multiple selectors are sometimes not intuitive. +For example ``mail.crit,*.err'' will select ``mail'' facility messages at +the level of ``err'' or higher, not at the level of ``crit'' or higher. +.Sh SEE ALSO +.Xr syslog 3 , +.Xr syslogd 8 diff --git a/syslogd.tproj/syslogd.8 b/syslogd.tproj/syslogd.8 new file mode 100644 index 0000000..f16297b --- /dev/null +++ b/syslogd.tproj/syslogd.8 @@ -0,0 +1,122 @@ +.\" Copyright (c) 1983, 1986, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)syslogd.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt SYSLOGD 8 +.Os BSD 4.2 +.Sh NAME +.Nm syslogd +.Nd log systems messages +.Sh SYNOPSIS +.Nm syslogd +.Op Fl f Ar config_file +.Op Fl m Ar mark_interval +.Op Fl p Ar log_socket +.Sh DESCRIPTION +.Nm Syslogd +reads and logs messages to the system console, log files, other +machines and/or users as specified by its configuration file. +The options are as follows: +.Bl -tag -width Ds +.It Fl f +Specify the pathname of an alternate configuration file; +the default is +.Pa /etc/syslog.conf . +.It Fl m +Select the number of minutes between ``mark'' messages; +the default is 20 minutes. +.It Fl p +Specify the pathname of an alternate log socket; +the default is +.Pa /var/run/syslog . +.El +.Pp +.Nm Syslogd +reads its configuration file when it starts up and whenever it +receives a hangup signal. +For information on the format of the configuration file, +see +.Xr syslog.conf 5 . +.Pp +.Nm Syslogd +reads messages from the +.Tn UNIX +domain socket +.Pa /var/run/syslog , +from an Internet domain socket specified in +.Pa /etc/services , +and from the special device +.Pa /dev/klog +(to read kernel messages). +.Pp +.Nm Syslogd +creates the file +.Pa /var/run/syslog.pid , +and stores its process +id there. +This can be used to kill or reconfigure +.Nm syslogd . +.Pp +The message sent to +.Nm syslogd +should consist of a single line. +The message can contain a priority code, which should be a preceding +decimal number in angle braces, for example, +.Sq Aq 5. +This priority code should map into the priorities defined in the +include file +.Aq Pa sys/syslog.h . +.Sh FILES +.Bl -tag -width /var/run/syslog.pid -compact +.It Pa /etc/syslog.conf +The configuration file. +.It Pa /var/run/syslog.pid +The process id of current +.Nm syslogd . +.It Pa /var/run/syslog +Name of the +.Tn UNIX +domain datagram log socket. +.It Pa /dev/klog +The kernel log device. +.El +.Sh SEE ALSO +.Xr logger 1 , +.Xr syslog 3 , +.Xr services 5 , +.Xr syslog.conf 5 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/syslogd.tproj/syslogd.c b/syslogd.tproj/syslogd.c new file mode 100644 index 0000000..27cb99b --- /dev/null +++ b/syslogd.tproj/syslogd.c @@ -0,0 +1,1162 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1988, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)syslogd.c 8.3 (Berkeley) 4/4/94"; +#endif /* not lint */ + +/* + * syslogd -- log system messages + * + * This program implements a system log. It takes a series of lines. + * Each line may have a priority, signified as "" as + * the first characters of the line. If this is + * not present, a default priority is used. + * + * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will + * cause it to reread its configuration file. + * + * Defined Constants: + * + * MAXLINE -- the maximimum line length that can be handled. + * DEFUPRI -- the default priority for user messages + * DEFSPRI -- the default priority for kernel messages + * + * Author: Eric Allman + * extensive changes by Ralph Campbell + * more extensive changes by Eric Allman (again) + */ + +#define MAXLINE 1024 /* maximum line length */ +#define MAXSVLINE 120 /* maximum saved line length */ +#define DEFUPRI (LOG_USER|LOG_NOTICE) +#define DEFSPRI (LOG_KERN|LOG_CRIT) +#define TIMERINTVL 30 /* interval for checking flush, mark */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +#define SYSLOG_NAMES +#include + +char *LogName = _PATH_LOG; +char *ConfFile = _PATH_LOGCONF; +char *PidFile = _PATH_LOGPID; +char ctty[] = _PATH_CONSOLE; + +#define FDMASK(fd) (1 << (fd)) + +#define dprintf if (Debug) printf + +#define MAXUNAMES 20 /* maximum number of user names */ + +/* + * Flags to logmsg(). + */ + +#define IGN_CONS 0x001 /* don't print on console */ +#define SYNC_FILE 0x002 /* do fsync on file after printing */ +#define ADDDATE 0x004 /* add a date to the message */ +#define MARK 0x008 /* this message is a mark */ + +/* + * This structure represents the files that will have log + * copies printed. + */ + +struct filed { + struct filed *f_next; /* next in linked list */ + short f_type; /* entry type, see below */ + short f_file; /* file descriptor */ + time_t f_time; /* time this was last written */ + u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ + union { + char f_uname[MAXUNAMES][UT_NAMESIZE+1]; + struct { + char f_hname[MAXHOSTNAMELEN+1]; + struct sockaddr_in f_addr; + } f_forw; /* forwarding address */ + char f_fname[MAXPATHLEN]; + } f_un; + char f_prevline[MAXSVLINE]; /* last message logged */ + char f_lasttime[16]; /* time of last occurrence */ + char f_prevhost[MAXHOSTNAMELEN+1]; /* host from which recd. */ + int f_prevpri; /* pri of f_prevline */ + int f_prevlen; /* length of f_prevline */ + int f_prevcount; /* repetition cnt of prevline */ + int f_repeatcount; /* number of "repeated" msgs */ +}; + +/* + * Intervals at which we flush out "message repeated" messages, + * in seconds after previous message is logged. After each flush, + * we move to the next interval until we reach the largest. + */ +int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ +#define MAXREPEAT ((sizeof(repeatinterval) / sizeof(repeatinterval[0])) - 1) +#define REPEATTIME(f) ((f)->f_time + repeatinterval[(f)->f_repeatcount]) +#define BACKOFF(f) { if (++(f)->f_repeatcount > MAXREPEAT) \ + (f)->f_repeatcount = MAXREPEAT; \ + } + +/* values for f_type */ +#define F_UNUSED 0 /* unused entry */ +#define F_FILE 1 /* regular file */ +#define F_TTY 2 /* terminal */ +#define F_CONSOLE 3 /* console terminal */ +#define F_FORW 4 /* remote machine */ +#define F_USERS 5 /* list of users */ +#define F_WALL 6 /* everyone logged on */ + +char *TypeNames[7] = { + "UNUSED", "FILE", "TTY", "CONSOLE", + "FORW", "USERS", "WALL" +}; + +struct filed *Files; +struct filed consfile; + +int Debug = 0; /* debug flag */ +int Insecure = 0; /* insecure flag */ +char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */ +char *LocalDomain; /* our local domain name */ +int InetInuse = 0; /* non-zero if INET sockets are being used */ +int finet; /* Internet datagram socket */ +int LogPort; /* port number for INET connections */ +int Initialized = 0; /* set when we have initialized ourselves */ +int MarkInterval = 20 * 60; /* interval between marks in seconds */ +int MarkSeq = 0; /* mark sequence number */ + +void cfline __P((char *, struct filed *)); +char *cvthname __P((struct sockaddr_in *)); +int decode __P((const char *, CODE *)); +void die __P((int)); +void domark __P((int)); +void fprintlog __P((struct filed *, int, char *)); +void init __P((int)); +void logerror __P((char *)); +void logmsg __P((int, char *, char *, int)); +void printline __P((char *, char *)); +void printsys __P((char *)); +void reapchild __P((int)); +char *ttymsg __P((struct iovec *, int, char *, int)); +void usage __P((void)); +void wallmsg __P((struct filed *, struct iovec *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int ch, funix, i, inetm, fklog, klogm, len; + struct sockaddr_un sunx, fromunix; + struct sockaddr_in sin, frominet; + FILE *fp; + char *p, line[MSG_BSIZE + 1]; + + while ((ch = getopt(argc, argv, "duf:m:p:")) != EOF) + switch(ch) { + case 'd': /* debug */ + Debug++; + break; + case 'u': /* insecure */ + Insecure++; + break; + case 'f': /* configuration file */ + ConfFile = optarg; + break; + case 'm': /* mark interval */ + MarkInterval = atoi(optarg) * 60; + break; + case 'p': /* path */ + LogName = optarg; + break; + case '?': + default: + usage(); + } + if ((argc -= optind) != 0) + usage(); + + if (!Debug) + (void)daemon(0, 0); + else + setlinebuf(stdout); + + consfile.f_type = F_CONSOLE; + (void)strcpy(consfile.f_un.f_fname, ctty); + (void)gethostname(LocalHostName, sizeof(LocalHostName)); + if ((p = strchr(LocalHostName, '.')) != NULL) { + *p++ = '\0'; + LocalDomain = p; + } else + LocalDomain = ""; + (void)signal(SIGTERM, die); + (void)signal(SIGINT, Debug ? die : SIG_IGN); + (void)signal(SIGQUIT, Debug ? die : SIG_IGN); + (void)signal(SIGCHLD, reapchild); + (void)signal(SIGALRM, domark); + (void)alarm(TIMERINTVL); + (void)unlink(LogName); + +#ifndef SUN_LEN +#define SUN_LEN(unp) (strlen((unp)->sun_path) + 2) +#endif + memset(&sunx, 0, sizeof(sunx)); + sunx.sun_family = AF_UNIX; + (void)strncpy(sunx.sun_path, LogName, sizeof(sunx.sun_path)); + funix = socket(AF_UNIX, SOCK_DGRAM, 0); + if (funix < 0 || + bind(funix, (struct sockaddr *)&sunx, SUN_LEN(&sunx)) < 0 || + chmod(LogName, 0666) < 0) { + (void) snprintf(line, sizeof line, "cannot create %s", LogName); + logerror(line); + dprintf("cannot create %s (%d)\n", LogName, errno); + die(0); + } + finet = socket(AF_INET, SOCK_DGRAM, 0); + inetm = 0; + if (finet >= 0) { + struct servent *sp; + + sp = getservbyname("syslog", "udp"); + if (sp == NULL) { + errno = 0; + logerror("syslog/udp: unknown service"); + die(0); + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_port = LogPort = sp->s_port; + if (bind(finet, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + logerror("bind"); + if (!Debug) + die(0); + } else { + inetm = FDMASK(finet); + InetInuse = 1; + } + } + if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) >= 0) + klogm = FDMASK(fklog); + else { + dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); + klogm = 0; + } + + /* tuck my process id away */ + fp = fopen(PidFile, "w"); + if (fp != NULL) { + fprintf(fp, "%d\n", getpid()); + (void) fclose(fp); + } + + dprintf("off & running....\n"); + + init(0); + (void)signal(SIGHUP, init); + + for (;;) { + int nfds, readfds = FDMASK(funix) | inetm | klogm; + + dprintf("readfds = %#x\n", readfds); + nfds = select(20, (fd_set *)&readfds, (fd_set *)NULL, + (fd_set *)NULL, (struct timeval *)NULL); + if (nfds == 0) + continue; + if (nfds < 0) { + if (errno != EINTR) + logerror("select"); + continue; + } + dprintf("got a message (%d, %#x)\n", nfds, readfds); + if (readfds & klogm) { + i = read(fklog, line, sizeof(line) - 1); + if (i > 0) { + line[i] = '\0'; + printsys(line); + } else if (i < 0 && errno != EINTR) { + logerror("klog"); + fklog = -1; + klogm = 0; + } + } + if (readfds & FDMASK(funix)) { + len = sizeof(fromunix); + i = recvfrom(funix, line, MAXLINE, 0, + (struct sockaddr *)&fromunix, &len); + if (i > 0) { + line[i] = '\0'; + printline(LocalHostName, line); + } else if (i < 0 && errno != EINTR) + logerror("recvfrom unix"); + } + if (readfds & inetm) { + len = sizeof(frominet); + i = recvfrom(finet, line, MAXLINE, 0, + (struct sockaddr *)&frominet, &len); + if (Insecure) { + if (i > 0) { + line[i] = '\0'; + printline(cvthname(&frominet), line); + } else if (i < 0 && errno != EINTR) + logerror("recvfrom inet"); + } + } + } +} + +void +usage() +{ + + (void)fprintf(stderr, + "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n"); + exit(1); +} + +/* + * Take a raw input line, decode the message, and print the message + * on the appropriate log files. + */ +void +printline(hname, msg) + char *hname; + char *msg; +{ + int c, pri; + char *p, *q, line[MAXLINE + 1]; + + /* test for special codes */ + pri = DEFUPRI; + p = msg; + if (*p == '<') { + pri = 0; + while (isdigit(*++p)) + pri = 10 * pri + (*p - '0'); + if (*p == '>') + ++p; + } + if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) + pri = DEFUPRI; + + /* don't allow users to log kernel messages */ + if (LOG_FAC(pri) == LOG_KERN) + pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); + + q = line; + + while ((c = *p++) != '\0' && + q < &line[sizeof(line) - 2]) { + c &= 0177; + if (iscntrl(c)) + if (c == '\n') + *q++ = ' '; + else if (c == '\t') + *q++ = '\t'; + else { + *q++ = '^'; + *q++ = c ^ 0100; + } + else + *q++ = c; + } + *q = '\0'; + + logmsg(pri, line, hname, 0); +} + +/* + * Take a raw input line from /dev/klog, split and format similar to syslog(). + */ +void +printsys(msg) + char *msg; +{ + int c, pri, flags; + char *lp, *p, *q, line[MAXLINE + 1]; + + (void)strcpy(line, "mach_kernel: "); + lp = line + strlen(line); + for (p = msg; *p != '\0'; ) { + flags = SYNC_FILE | ADDDATE; /* fsync file after write */ + pri = DEFSPRI; + if (*p == '<') { + pri = 0; + while (isdigit(*++p)) + pri = 10 * pri + (*p - '0'); + if (*p == '>') + ++p; + } else { + /* kernel printf's come out on console */ + flags |= IGN_CONS; + } + if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) + pri = DEFSPRI; + q = lp; + while (*p != '\0' && (c = *p++) != '\n' && + q < &line[MAXLINE]) + *q++ = c; + *q = '\0'; + logmsg(pri, line, LocalHostName, flags); + } +} + +time_t now; + +/* + * Log a message to the appropriate log files, users, etc. based on + * the priority. + */ +void +logmsg(pri, msg, from, flags) + int pri; + char *msg, *from; + int flags; +{ + struct filed *f; + int fac, msglen, omask, prilev; + char *timestamp; + + dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", + pri, flags, from, msg); + + omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM)); + + /* + * Check to see if msg looks non-standard. + */ + msglen = strlen(msg); + if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' || + msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') + flags |= ADDDATE; + + (void)time(&now); + if (flags & ADDDATE) + timestamp = ctime(&now) + 4; + else { + timestamp = msg; + msg += 16; + msglen -= 16; + } + + /* extract facility and priority level */ + if (flags & MARK) + fac = LOG_NFACILITIES; + else + fac = LOG_FAC(pri); + prilev = LOG_PRI(pri); + + /* log the message to the particular outputs */ + if (!Initialized) { + f = &consfile; + f->f_file = open(ctty, O_WRONLY, 0); + + if (f->f_file >= 0) { + fprintlog(f, flags, msg); + (void)close(f->f_file); + } + (void)sigsetmask(omask); + return; + } + for (f = Files; f; f = f->f_next) { + /* skip messages that are incorrect priority */ + if (f->f_pmask[fac] < prilev || + f->f_pmask[fac] == INTERNAL_NOPRI) + continue; + + if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) + continue; + + /* don't output marks to recently written files */ + if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2) + continue; + + /* + * suppress duplicate lines to this file + */ + if ((flags & MARK) == 0 && msglen == f->f_prevlen && + !strcmp(msg, f->f_prevline) && + !strcmp(from, f->f_prevhost)) { + (void)strncpy(f->f_lasttime, timestamp, 15); + f->f_prevcount++; + dprintf("msg repeated %d times, %ld sec of %d\n", + f->f_prevcount, now - f->f_time, + repeatinterval[f->f_repeatcount]); + /* + * If domark would have logged this by now, + * flush it now (so we don't hold isolated messages), + * but back off so we'll flush less often + * in the future. + */ + if (now > REPEATTIME(f)) { + fprintlog(f, flags, (char *)NULL); + BACKOFF(f); + } + } else { + /* new line, save it */ + if (f->f_prevcount) + fprintlog(f, 0, (char *)NULL); + f->f_repeatcount = 0; + (void)strncpy(f->f_lasttime, timestamp, 15); + (void)strncpy(f->f_prevhost, from, + sizeof(f->f_prevhost)); + if (msglen < MAXSVLINE) { + f->f_prevlen = msglen; + f->f_prevpri = pri; + (void)strcpy(f->f_prevline, msg); + fprintlog(f, flags, (char *)NULL); + } else { + f->f_prevline[0] = 0; + f->f_prevlen = 0; + fprintlog(f, flags, msg); + } + } + } + (void)sigsetmask(omask); +} + +void +fprintlog(f, flags, msg) + struct filed *f; + int flags; + char *msg; +{ + struct iovec iov[6]; + struct iovec *v; + int l; + char line[MAXLINE + 1], repbuf[80], greetings[200]; + + v = iov; + if (f->f_type == F_WALL) { + v->iov_base = greetings; + v->iov_len = snprintf(greetings, sizeof greetings, + "\r\n\7Message from syslogd@%s at %.24s ...\r\n", + f->f_prevhost, ctime(&now)); + v++; + v->iov_base = ""; + v->iov_len = 0; + v++; + } else { + v->iov_base = f->f_lasttime; + v->iov_len = 15; + v++; + v->iov_base = " "; + v->iov_len = 1; + v++; + } + v->iov_base = f->f_prevhost; + v->iov_len = strlen(v->iov_base); + v++; + v->iov_base = " "; + v->iov_len = 1; + v++; + + if (msg) { + v->iov_base = msg; + v->iov_len = strlen(msg); + } else if (f->f_prevcount > 1) { + v->iov_base = repbuf; + v->iov_len = snprintf(repbuf, sizeof repbuf, "last message repeated %d times", + f->f_prevcount); + } else { + v->iov_base = f->f_prevline; + v->iov_len = f->f_prevlen; + } + v++; + + dprintf("Logging to %s", TypeNames[f->f_type]); + f->f_time = now; + + switch (f->f_type) { + case F_UNUSED: + dprintf("\n"); + break; + + case F_FORW: + dprintf(" %s\n", f->f_un.f_forw.f_hname); + l = snprintf(line, sizeof line, "<%d>%.15s %s", f->f_prevpri, + iov[0].iov_base, iov[4].iov_base); + if (l > MAXLINE) + l = MAXLINE; + if (sendto(finet, line, l, 0, + (struct sockaddr *)&f->f_un.f_forw.f_addr, + sizeof(f->f_un.f_forw.f_addr)) != l) { + int e = errno; + (void)close(f->f_file); + f->f_type = F_UNUSED; + errno = e; + logerror("sendto"); + } + break; + + case F_CONSOLE: + if (flags & IGN_CONS) { + dprintf(" (ignored)\n"); + break; + } + /* FALLTHROUGH */ + + case F_TTY: + case F_FILE: + dprintf(" %s\n", f->f_un.f_fname); + if (f->f_type != F_FILE) { + v->iov_base = "\r\n"; + v->iov_len = 2; + } else { + v->iov_base = "\n"; + v->iov_len = 1; + } + again: + if (writev(f->f_file, iov, 6) < 0) { + int e = errno; + (void)close(f->f_file); + /* + * Check for errors on TTY's due to loss of tty + */ + if ((e == EIO || e == EBADF) && f->f_type != F_FILE) { + f->f_file = open(f->f_un.f_fname, + O_WRONLY|O_APPEND, 0); + if (f->f_file < 0) { + f->f_type = F_UNUSED; + logerror(f->f_un.f_fname); + } else + goto again; + } else { + f->f_type = F_UNUSED; + errno = e; + logerror(f->f_un.f_fname); + } + } else if (flags & SYNC_FILE) + (void)fsync(f->f_file); + break; + + case F_USERS: + case F_WALL: + dprintf("\n"); + v->iov_base = "\r\n"; + v->iov_len = 2; + wallmsg(f, iov); + break; + } + f->f_prevcount = 0; +} + +/* + * WALLMSG -- Write a message to the world at large + * + * Write the specified message to either the entire + * world, or a list of approved users. + */ +void +wallmsg(f, iov) + struct filed *f; + struct iovec *iov; +{ + static int reenter; /* avoid calling ourselves */ + FILE *uf; + struct utmp ut; + int i; + char *p; + char line[sizeof(ut.ut_line) + 1]; + + if (reenter++) + return; + if ((uf = fopen(_PATH_UTMP, "r")) == NULL) { + logerror(_PATH_UTMP); + reenter = 0; + return; + } + /* NOSTRICT */ + while (fread((char *)&ut, sizeof(ut), 1, uf) == 1) { + if (ut.ut_name[0] == '\0') + continue; + strncpy(line, ut.ut_line, sizeof(ut.ut_line)); + line[sizeof(ut.ut_line)] = '\0'; + if (f->f_type == F_WALL) { + if ((p = ttymsg(iov, 6, line, 60*5)) != NULL) { + errno = 0; /* already in msg */ + logerror(p); + } + continue; + } + /* should we send the message to this user? */ + for (i = 0; i < MAXUNAMES; i++) { + if (!f->f_un.f_uname[i][0]) + break; + if (!strncmp(f->f_un.f_uname[i], ut.ut_name, + UT_NAMESIZE)) { + if ((p = ttymsg(iov, 6, line, 60*5)) != NULL) { + errno = 0; /* already in msg */ + logerror(p); + } + break; + } + } + } + (void)fclose(uf); + reenter = 0; +} + +void +reapchild(signo) + int signo; +{ + union wait status; + + while (wait3((int *)&status, WNOHANG, (struct rusage *)NULL) > 0) + ; +} + +/* + * Return a printable representation of a host address. + */ +char * +cvthname(f) + struct sockaddr_in *f; +{ + struct hostent *hp; + char *p; + + dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr)); + + if (f->sin_family != AF_INET) { + dprintf("Malformed from address\n"); + return ("???"); + } + hp = gethostbyaddr((char *)&f->sin_addr, + sizeof(struct in_addr), f->sin_family); + if (hp == 0) { + dprintf("Host name for your address (%s) unknown\n", + inet_ntoa(f->sin_addr)); + return (inet_ntoa(f->sin_addr)); + } + if ((p = strchr(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0) + *p = '\0'; + return (hp->h_name); +} + +void +domark(signo) + int signo; +{ + struct filed *f; + + now = time((time_t *)NULL); + MarkSeq += TIMERINTVL; + if (MarkSeq >= MarkInterval) { + logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK); + MarkSeq = 0; + } + + for (f = Files; f; f = f->f_next) { + if (f->f_prevcount && now >= REPEATTIME(f)) { + dprintf("flush %s: repeated %d times, %d sec.\n", + TypeNames[f->f_type], f->f_prevcount, + repeatinterval[f->f_repeatcount]); + fprintlog(f, 0, (char *)NULL); + BACKOFF(f); + } + } + (void)alarm(TIMERINTVL); +} + +/* + * Print syslogd errors some place. + */ +void +logerror(type) + char *type; +{ + char buf[100]; + + if (errno) + (void)snprintf(buf, + sizeof(buf), "syslogd: %s: %s", type, strerror(errno)); + else + (void)snprintf(buf, sizeof(buf), "syslogd: %s", type); + errno = 0; + dprintf("%s\n", buf); + logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); +} + +void +die(signo) + int signo; +{ + struct filed *f; + char buf[100]; + + for (f = Files; f != NULL; f = f->f_next) { + /* flush any pending output */ + if (f->f_prevcount) + fprintlog(f, 0, (char *)NULL); + } + if (signo) { + dprintf("syslogd: exiting on signal %d\n", signo); + (void)snprintf(buf, sizeof buf, "exiting on signal %d", signo); + errno = 0; + logerror(buf); + } + (void)unlink(LogName); + exit(0); +} + +/* + * INIT -- Initialize syslogd from configuration table + */ +void +init(signo) + int signo; +{ + int i; + FILE *cf; + struct filed *f, *next, **nextp; + char *p; + char cline[LINE_MAX]; + + dprintf("init\n"); + + /* + * Close all open log files. + */ + Initialized = 0; + for (f = Files; f != NULL; f = next) { + /* flush any pending output */ + if (f->f_prevcount) + fprintlog(f, 0, (char *)NULL); + + switch (f->f_type) { + case F_FILE: + case F_TTY: + case F_CONSOLE: + case F_FORW: + (void)close(f->f_file); + break; + } + next = f->f_next; + free((char *)f); + } + Files = NULL; + nextp = &Files; + + /* open the configuration file */ + if ((cf = fopen(ConfFile, "r")) == NULL) { + dprintf("cannot open %s\n", ConfFile); + *nextp = (struct filed *)calloc(1, sizeof(*f)); + cfline("*.ERR\t/dev/console", *nextp); + (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)); + cfline("*.PANIC\t*", (*nextp)->f_next); + Initialized = 1; + return; + } + + /* + * Foreach line in the conf table, open that file. + */ + f = NULL; + while (fgets(cline, sizeof(cline), cf) != NULL) { + /* + * check for end-of-section, comments, strip off trailing + * spaces and newline character. + */ + for (p = cline; isspace(*p); ++p) + continue; + if (*p == NULL || *p == '#') + continue; + for (p = strchr(cline, '\0'); isspace(*--p);) + continue; + *++p = '\0'; + f = (struct filed *)calloc(1, sizeof(*f)); + *nextp = f; + nextp = &f->f_next; + cfline(cline, f); + } + + /* close the configuration file */ + (void)fclose(cf); + + Initialized = 1; + + if (Debug) { + for (f = Files; f; f = f->f_next) { + for (i = 0; i <= LOG_NFACILITIES; i++) + if (f->f_pmask[i] == INTERNAL_NOPRI) + printf("X "); + else + printf("%d ", f->f_pmask[i]); + printf("%s: ", TypeNames[f->f_type]); + switch (f->f_type) { + case F_FILE: + case F_TTY: + case F_CONSOLE: + printf("%s", f->f_un.f_fname); + break; + + case F_FORW: + printf("%s", f->f_un.f_forw.f_hname); + break; + + case F_USERS: + for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++) + printf("%s, ", f->f_un.f_uname[i]); + break; + } + printf("\n"); + } + } + + logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE); + dprintf("syslogd: restarted\n"); +} + +/* + * Crack a configuration file line + */ +void +cfline(line, f) + char *line; + struct filed *f; +{ + struct hostent *hp; + int i, pri; + char *bp, *p, *q; + char buf[MAXLINE], ebuf[100]; + + dprintf("cfline(%s)\n", line); + + errno = 0; /* keep strerror() stuff out of logerror messages */ + + /* clear out file entry */ + memset(f, 0, sizeof(*f)); + for (i = 0; i <= LOG_NFACILITIES; i++) + f->f_pmask[i] = INTERNAL_NOPRI; + + /* scan through the list of selectors */ + for (p = line; *p && *p != '\t';) { + + /* find the end of this facility name list */ + for (q = p; *q && *q != '\t' && *q++ != '.'; ) + continue; + + /* collect priority name */ + for (bp = buf; *q && !strchr("\t,;", *q); ) + *bp++ = *q++; + *bp = '\0'; + + /* skip cruft */ + while (strchr(", ;", *q)) + q++; + + /* decode priority name */ + if (*buf == '*') + pri = LOG_PRIMASK + 1; + else { + pri = decode(buf, prioritynames); + if (pri < 0) { + (void)snprintf(ebuf, sizeof ebuf, + "unknown priority name \"%s\"", buf); + logerror(ebuf); + return; + } + } + + /* scan facilities */ + while (*p && !strchr("\t.;", *p)) { + for (bp = buf; *p && !strchr("\t,;.", *p); ) + *bp++ = *p++; + *bp = '\0'; + if (*buf == '*') + for (i = 0; i < LOG_NFACILITIES; i++) + f->f_pmask[i] = pri; + else { + i = decode(buf, facilitynames); + if (i < 0) { + (void)snprintf(ebuf, sizeof ebuf, + "unknown facility name \"%s\"", + buf); + logerror(ebuf); + return; + } + f->f_pmask[i >> 3] = pri; + } + while (*p == ',' || *p == ' ') + p++; + } + + p = q; + } + + /* skip to action part */ + while (*p == '\t') + p++; + + switch (*p) + { + case '@': + if (!InetInuse) + break; + (void)strcpy(f->f_un.f_forw.f_hname, ++p); + hp = gethostbyname(p); + if (hp == NULL) { + extern int h_errno; + + logerror(hstrerror(h_errno)); + break; + } + memset(&f->f_un.f_forw.f_addr, 0, + sizeof(f->f_un.f_forw.f_addr)); + f->f_un.f_forw.f_addr.sin_family = AF_INET; + f->f_un.f_forw.f_addr.sin_port = LogPort; + memmove(&f->f_un.f_forw.f_addr.sin_addr, hp->h_addr, hp->h_length); + f->f_type = F_FORW; + break; + + case '/': + (void)strcpy(f->f_un.f_fname, p); + if ((f->f_file = open(p, O_WRONLY|O_APPEND, 0)) < 0) { + f->f_file = F_UNUSED; + logerror(p); + break; + } + if (isatty(f->f_file)) + f->f_type = F_TTY; + else + f->f_type = F_FILE; + if (strcmp(p, ctty) == 0) + f->f_type = F_CONSOLE; + break; + + case '*': + f->f_type = F_WALL; + break; + + default: + for (i = 0; i < MAXUNAMES && *p; i++) { + for (q = p; *q && *q != ','; ) + q++; + (void)strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE); + if ((q - p) > UT_NAMESIZE) + f->f_un.f_uname[i][UT_NAMESIZE] = '\0'; + else + f->f_un.f_uname[i][q - p] = '\0'; + while (*q == ',' || *q == ' ') + q++; + p = q; + } + f->f_type = F_USERS; + break; + } +} + + +/* + * Decode a symbolic name to a numeric value + */ +int +decode(name, codetab) + const char *name; + CODE *codetab; +{ + CODE *c; + char *p, buf[40]; + + if (isdigit(*name)) + return (atoi(name)); + + for (p = buf; *name && p < &buf[sizeof(buf) - 1]; p++, name++) { + if (isupper(*name)) + *p = tolower(*name); + else + *p = *name; + } + *p = '\0'; + for (c = codetab; c->c_name; c++) + if (!strcmp(buf, c->c_name)) + return (c->c_val); + + return (-1); +} diff --git a/talk.tproj/Makefile b/talk.tproj/Makefile new file mode 100644 index 0000000..de9a8fa --- /dev/null +++ b/talk.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = talk + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = talk.h talk_ctl.h + +CFILES = ctl.c ctl_transact.c display.c get_addrs.c get_names.c\ + init_disp.c invite.c io.c look_up.c msgs.c talk.c + +OTHERSRCS = Makefile.preamble Makefile talk.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/talk.tproj/Makefile.preamble b/talk.tproj/Makefile.preamble new file mode 100644 index 0000000..925a5c7 --- /dev/null +++ b/talk.tproj/Makefile.preamble @@ -0,0 +1,3 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/talk.tproj/PB.project b/talk.tproj/PB.project new file mode 100644 index 0000000..f6093c3 --- /dev/null +++ b/talk.tproj/PB.project @@ -0,0 +1,37 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (talk.h, talk_ctl.h); + OTHER_LIBS = (); + OTHER_LINKED = ( + ctl.c, + ctl_transact.c, + display.c, + get_addrs.c, + get_names.c, + init_disp.c, + invite.c, + io.c, + look_up.c, + msgs.c, + talk.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, talk.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = talk; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/talk.tproj/ctl.c b/talk.tproj/ctl.c new file mode 100644 index 0000000..d1c016b --- /dev/null +++ b/talk.tproj/ctl.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * This file handles haggling with the various talk daemons to + * get a socket to talk to. sockt is opened and connected in + * the progress + */ + +#include +#include +#include +#include +#include "talk.h" +#include "talk_ctl.h" + +struct sockaddr_in daemon_addr = { sizeof(daemon_addr), AF_INET }; +struct sockaddr_in ctl_addr = { sizeof(ctl_addr), AF_INET }; +struct sockaddr_in my_addr = { sizeof(my_addr), AF_INET }; + + /* inet addresses of the two machines */ +struct in_addr my_machine_addr; +struct in_addr his_machine_addr; + +u_short daemon_port; /* port number of the talk daemon */ + +int ctl_sockt; +int sockt; +int invitation_waiting = 0; + +CTL_MSG msg; + +open_sockt() +{ + int length; + + my_addr.sin_addr = my_machine_addr; + my_addr.sin_port = 0; + sockt = socket(AF_INET, SOCK_STREAM, 0); + if (sockt <= 0) + p_error("Bad socket"); + if (bind(sockt, (struct sockaddr *)&my_addr, sizeof(my_addr)) != 0) + p_error("Binding local socket"); + length = sizeof(my_addr); + if (getsockname(sockt, (struct sockaddr *)&my_addr, &length) == -1) + p_error("Bad address for socket"); +} + +/* open the ctl socket */ +open_ctl() +{ + int length; + + ctl_addr.sin_port = 0; + ctl_addr.sin_addr = my_machine_addr; + ctl_sockt = socket(AF_INET, SOCK_DGRAM, 0); + if (ctl_sockt <= 0) + p_error("Bad socket"); + if (bind(ctl_sockt, + (struct sockaddr *)&ctl_addr, sizeof(ctl_addr)) != 0) + p_error("Couldn't bind to control socket"); + length = sizeof(ctl_addr); + if (getsockname(ctl_sockt, + (struct sockaddr *)&ctl_addr, &length) == -1) + p_error("Bad address for ctl socket"); +} + +/* print_addr is a debug print routine */ +print_addr(addr) + struct sockaddr_in addr; +{ + int i; + + printf("addr = %x, port = %o, family = %o zero = ", + addr.sin_addr, addr.sin_port, addr.sin_family); + for (i = 0; i<8;i++) + printf("%o ", (int)addr.sin_zero[i]); + putchar('\n'); +} diff --git a/talk.tproj/ctl_transact.c b/talk.tproj/ctl_transact.c new file mode 100644 index 0000000..85474dd --- /dev/null +++ b/talk.tproj/ctl_transact.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include "talk_ctl.h" + +#define CTL_WAIT 2 /* time to wait for a response, in seconds */ + +/* + * SOCKDGRAM is unreliable, so we must repeat messages if we have + * not recieved an acknowledgement within a reasonable amount + * of time + */ +ctl_transact(target, msg, type, rp) + struct in_addr target; + CTL_MSG msg; + int type; + CTL_RESPONSE *rp; +{ + int read_mask, ctl_mask, nready, cc; + struct timeval wait; + + msg.type = type; + daemon_addr.sin_addr = target; + daemon_addr.sin_port = daemon_port; + ctl_mask = 1 << ctl_sockt; + + /* + * Keep sending the message until a response of + * the proper type is obtained. + */ + do { + wait.tv_sec = CTL_WAIT; + wait.tv_usec = 0; + /* resend message until a response is obtained */ + do { + cc = sendto(ctl_sockt, (char *)&msg, sizeof (msg), 0, + (struct sockaddr *)&daemon_addr, + sizeof (daemon_addr)); + if (cc != sizeof (msg)) { + if (errno == EINTR) + continue; + p_error("Error on write to talk daemon"); + } + read_mask = ctl_mask; + nready = select(32, &read_mask, 0, 0, &wait); + if (nready < 0) { + if (errno == EINTR) + continue; + p_error("Error waiting for daemon response"); + } + } while (nready == 0); + /* + * Keep reading while there are queued messages + * (this is not necessary, it just saves extra + * request/acknowledgements being sent) + */ + do { + cc = recv(ctl_sockt, (char *)rp, sizeof (*rp), 0); + if (cc < 0) { + if (errno == EINTR) + continue; + p_error("Error on read from talk daemon"); + } + read_mask = ctl_mask; + /* an immediate poll */ + timerclear(&wait); + nready = select(32, &read_mask, 0, 0, &wait); + } while (nready > 0 && (rp->vers != TALK_VERSION || + rp->type != type)); + } while (rp->vers != TALK_VERSION || rp->type != type); + rp->id_num = ntohl(rp->id_num); + rp->addr.sa_family = ntohs(rp->addr.sa_family); +} diff --git a/talk.tproj/display.c b/talk.tproj/display.c new file mode 100644 index 0000000..6a725a6 --- /dev/null +++ b/talk.tproj/display.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * The window 'manager', initializes curses and handles the actual + * displaying of text + */ +#include "talk.h" + +xwin_t my_win; +xwin_t his_win; +WINDOW *line_win; + +int curses_initialized = 0; + +/* + * max HAS to be a function, it is called with + * a argument of the form --foo at least once. + */ +max(a,b) + int a, b; +{ + + return (a > b ? a : b); +} + +/* + * Display some text on somebody's window, processing some control + * characters while we are at it. + */ +display(win, text, size) + register xwin_t *win; + register char *text; + int size; +{ + register int i; + char cch; + + for (i = 0; i < size; i++) { + if (*text == '\n') { + xscroll(win, 0); + text++; + continue; + } + /* erase character */ + if (*text == win->cerase) { + wmove(win->x_win, win->x_line, max(--win->x_col, 0)); + getyx(win->x_win, win->x_line, win->x_col); + waddch(win->x_win, ' '); + wmove(win->x_win, win->x_line, win->x_col); + getyx(win->x_win, win->x_line, win->x_col); + text++; + continue; + } + /* + * On word erase search backwards until we find + * the beginning of a word or the beginning of + * the line. + */ + if (*text == win->werase) { + int endcol, xcol, i, c; + + endcol = win->x_col; + xcol = endcol - 1; + while (xcol >= 0) { + c = readwin(win->x_win, win->x_line, xcol); + if (c != ' ') + break; + xcol--; + } + while (xcol >= 0) { + c = readwin(win->x_win, win->x_line, xcol); + if (c == ' ') + break; + xcol--; + } + wmove(win->x_win, win->x_line, xcol + 1); + for (i = xcol + 1; i < endcol; i++) + waddch(win->x_win, ' '); + wmove(win->x_win, win->x_line, xcol + 1); + getyx(win->x_win, win->x_line, win->x_col); + text++; + continue; + } + /* line kill */ + if (*text == win->kill) { + wmove(win->x_win, win->x_line, 0); + wclrtoeol(win->x_win); + getyx(win->x_win, win->x_line, win->x_col); + text++; + continue; + } + if (*text == '\f') { + if (win == &my_win) + wrefresh(curscr); + text++; + continue; + } + if (win->x_col == COLS-1) { + /* check for wraparound */ + xscroll(win, 0); + } + if (*text < ' ' && *text != '\t') { + waddch(win->x_win, '^'); + getyx(win->x_win, win->x_line, win->x_col); + if (win->x_col == COLS-1) /* check for wraparound */ + xscroll(win, 0); + cch = (*text & 63) + 64; + waddch(win->x_win, cch); + } else + waddch(win->x_win, *text); + getyx(win->x_win, win->x_line, win->x_col); + text++; + } + wrefresh(win->x_win); +} + +/* + * Read the character at the indicated position in win + */ +readwin(win, line, col) + WINDOW *win; +{ + int oldline, oldcol; + register int c; + + getyx(win, oldline, oldcol); + wmove(win, line, col); + c = winch(win); + wmove(win, oldline, oldcol); + return (c); +} + +/* + * Scroll a window, blanking out the line following the current line + * so that the current position is obvious + */ +xscroll(win, flag) + register xwin_t *win; + int flag; +{ + + if (flag == -1) { + wmove(win->x_win, 0, 0); + win->x_line = 0; + win->x_col = 0; + return; + } + win->x_line = (win->x_line + 1) % win->x_nlines; + win->x_col = 0; + wmove(win->x_win, win->x_line, win->x_col); + wclrtoeol(win->x_win); + wmove(win->x_win, (win->x_line + 1) % win->x_nlines, win->x_col); + wclrtoeol(win->x_win); + wmove(win->x_win, win->x_line, win->x_col); +} diff --git a/talk.tproj/get_addrs.c b/talk.tproj/get_addrs.c new file mode 100644 index 0000000..ce728c5 --- /dev/null +++ b/talk.tproj/get_addrs.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include "talk_ctl.h" + +get_addrs(my_machine_name, his_machine_name) + char *my_machine_name, *his_machine_name; +{ + struct hostent *hp; + struct servent *sp; + + msg.pid = htonl(getpid()); + /* look up the address of the local host */ + hp = gethostbyname(my_machine_name); + if (hp == NULL) { + fprintf(stderr, "talk: %s: ", my_machine_name); + herror((char *)NULL); + exit(-1); + } + bcopy(hp->h_addr, (char *)&my_machine_addr, hp->h_length); + /* + * If the callee is on-machine, just copy the + * network address, otherwise do a lookup... + */ + if (strcmp(his_machine_name, my_machine_name)) { + hp = gethostbyname(his_machine_name); + if (hp == NULL) { + fprintf(stderr, "talk: %s: ", his_machine_name); + herror((char *)NULL); + exit(-1); + } + bcopy(hp->h_addr, (char *) &his_machine_addr, hp->h_length); + } else + his_machine_addr = my_machine_addr; + /* find the server's port */ + sp = getservbyname("ntalk", "udp"); + if (sp == 0) { + fprintf(stderr, "talk: %s/%s: service is not registered.\n", + "ntalk", "udp"); + exit(-1); + } + daemon_port = sp->s_port; +} diff --git a/talk.tproj/get_names.c b/talk.tproj/get_names.c new file mode 100644 index 0000000..adf43bc --- /dev/null +++ b/talk.tproj/get_names.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include "talk.h" + +char *getlogin(); +char *ttyname(); +char *rindex(); +extern CTL_MSG msg; + +/* + * Determine the local and remote user, tty, and machines + */ +get_names(argc, argv) + int argc; + char *argv[]; +{ + char hostname[MAXHOSTNAMELEN]; + char *his_name, *my_name; + char *my_machine_name, *his_machine_name; + char *my_tty, *his_tty; + register char *cp; + + if (argc < 2 ) { + printf("Usage: talk user [ttyname]\n"); + exit(-1); + } + if (!isatty(0)) { + printf("Standard input must be a tty, not a pipe or a file\n"); + exit(-1); + } + if ((my_name = getlogin()) == NULL) { + struct passwd *pw; + + if ((pw = getpwuid(getuid())) == NULL) { + printf("You don't exist. Go away.\n"); + exit(-1); + } + my_name = pw->pw_name; + } + gethostname(hostname, sizeof (hostname)); + my_machine_name = hostname; + /* check for, and strip out, the machine name of the target */ + for (cp = argv[1]; *cp && !index("@:!.", *cp); cp++) + ; + if (*cp == '\0') { + /* this is a local to local talk */ + his_name = argv[1]; + his_machine_name = my_machine_name; + } else { + if (*cp++ == '@') { + /* user@host */ + his_name = argv[1]; + his_machine_name = cp; + } else { + /* host.user or host!user or host:user */ + his_name = cp; + his_machine_name = argv[1]; + } + *--cp = '\0'; + } + if (argc > 2) + his_tty = argv[2]; /* tty name is arg 2 */ + else + his_tty = ""; + get_addrs(my_machine_name, his_machine_name); + /* + * Initialize the message template. + */ + msg.vers = TALK_VERSION; + msg.addr.sa_family = htons(AF_INET); + msg.ctl_addr.sa_family = htons(AF_INET); + msg.id_num = htonl(0); + strncpy(msg.l_name, my_name, NAME_SIZE); + msg.l_name[NAME_SIZE - 1] = '\0'; + strncpy(msg.r_name, his_name, NAME_SIZE); + msg.r_name[NAME_SIZE - 1] = '\0'; + strncpy(msg.r_tty, his_tty, TTY_SIZE); + msg.r_tty[TTY_SIZE - 1] = '\0'; +} diff --git a/talk.tproj/init_disp.c b/talk.tproj/init_disp.c new file mode 100644 index 0000000..1332107 --- /dev/null +++ b/talk.tproj/init_disp.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * Initialization code for the display package, + * as well as the signal handling routines. + */ + +#include +#include + +#include +#include +#include "talk.h" + +/* + * Set up curses, catch the appropriate signals, + * and build the various windows. + */ +init_display() +{ + void sig_sent(); + struct sigvec sigv; + + if (initscr() == NULL) + errx(1, "Terminal type unset or lacking necessary features."); + (void) sigvec(SIGTSTP, (struct sigvec *)0, &sigv); + sigv.sv_mask |= sigmask(SIGALRM); + (void) _sigvec_nobind(SIGTSTP, &sigv, (struct sigvec *)0); + curses_initialized = 1; + clear(); + refresh(); + noecho(); + crmode(); + signal(SIGINT, sig_sent); + signal(SIGPIPE, sig_sent); + /* curses takes care of ^Z */ + my_win.x_nlines = LINES / 2; + my_win.x_ncols = COLS; + my_win.x_win = newwin(my_win.x_nlines, my_win.x_ncols, 0, 0); + scrollok(my_win.x_win, FALSE); + wclear(my_win.x_win); + + his_win.x_nlines = LINES / 2 - 1; + his_win.x_ncols = COLS; + his_win.x_win = newwin(his_win.x_nlines, his_win.x_ncols, + my_win.x_nlines+1, 0); + scrollok(his_win.x_win, FALSE); + wclear(his_win.x_win); + + line_win = newwin(1, COLS, my_win.x_nlines, 0); + box(line_win, '-', '-'); + wrefresh(line_win); + /* let them know we are working on it */ + current_state = "No connection yet"; +} + +/* + * Trade edit characters with the other talk. By agreement + * the first three characters each talk transmits after + * connection are the three edit characters. + */ +set_edit_chars() +{ + char buf[3]; + int cc; + struct sgttyb tty; + struct ltchars ltc; + + ioctl(0, TIOCGETP, &tty); + ioctl(0, TIOCGLTC, (struct sgttyb *)<c); + my_win.cerase = tty.sg_erase; + my_win.kill = tty.sg_kill; + if (ltc.t_werasc == (char) -1) + my_win.werase = '\027'; /* control W */ + else + my_win.werase = ltc.t_werasc; + buf[0] = my_win.cerase; + buf[1] = my_win.kill; + buf[2] = my_win.werase; + cc = write(sockt, buf, sizeof(buf)); + if (cc != sizeof(buf) ) + p_error("Lost the connection"); + cc = read(sockt, buf, sizeof(buf)); + if (cc != sizeof(buf) ) + p_error("Lost the connection"); + his_win.cerase = buf[0]; + his_win.kill = buf[1]; + his_win.werase = buf[2]; +} + +void +sig_sent() +{ + + message("Connection closing. Exiting"); + quit(); +} + +/* + * All done talking...hang up the phone and reset terminal thingy's + */ +quit() +{ + + if (curses_initialized) { + wmove(his_win.x_win, his_win.x_nlines-1, 0); + wclrtoeol(his_win.x_win); + wrefresh(his_win.x_win); + endwin(); + } + if (invitation_waiting) + send_delete(); + exit(0); +} diff --git a/talk.tproj/invite.c b/talk.tproj/invite.c new file mode 100644 index 0000000..47fbf44 --- /dev/null +++ b/talk.tproj/invite.c @@ -0,0 +1,208 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include "talk_ctl.h" +#include "talk.h" + +/* + * There wasn't an invitation waiting, so send a request containing + * our sockt address to the remote talk daemon so it can invite + * him + */ + +/* + * The msg.id's for the invitations + * on the local and remote machines. + * These are used to delete the + * invitations. + */ +int local_id, remote_id; +void re_invite(); +jmp_buf invitebuf; + +invite_remote() +{ + int nfd, read_mask, template, new_sockt; + struct itimerval itimer; + CTL_RESPONSE response; + + itimer.it_value.tv_sec = RING_WAIT; + itimer.it_value.tv_usec = 0; + itimer.it_interval = itimer.it_value; + if (listen(sockt, 5) != 0) + p_error("Error on attempt to listen for caller"); +#ifdef MSG_EOR + /* copy new style sockaddr to old, swap family (short in old) */ + msg.addr = *(struct osockaddr *)&my_addr; /* XXX new to old style*/ + msg.addr.sa_family = htons(my_addr.sin_family); +#else + msg.addr = *(struct sockaddr *)&my_addr; +#endif + msg.id_num = htonl(-1); /* an impossible id_num */ + invitation_waiting = 1; + announce_invite(); + /* + * Shut off the automatic messages for a while, + * so we can use the interupt timer to resend the invitation + */ + end_msgs(); + setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); + message("Waiting for your party to respond"); + signal(SIGALRM, re_invite); + (void) setjmp(invitebuf); + while ((new_sockt = accept(sockt, 0, 0)) < 0) { + if (errno == EINTR) + continue; + p_error("Unable to connect with your party"); + } + close(sockt); + sockt = new_sockt; + + /* + * Have the daemons delete the invitations now that we + * have connected. + */ + current_state = "Waiting for your party to respond"; + start_msgs(); + + msg.id_num = htonl(local_id); + ctl_transact(my_machine_addr, msg, DELETE, &response); + msg.id_num = htonl(remote_id); + ctl_transact(his_machine_addr, msg, DELETE, &response); + invitation_waiting = 0; +} + +/* + * Routine called on interupt to re-invite the callee + */ +void +re_invite() +{ + + message("Ringing your party again"); + current_line++; + /* force a re-announce */ + msg.id_num = htonl(remote_id + 1); + announce_invite(); + longjmp(invitebuf, 1); +} + +static char *answers[] = { + "answer #0", /* SUCCESS */ + "Your party is not logged on", /* NOT_HERE */ + "Target machine is too confused to talk to us", /* FAILED */ + "Target machine does not recognize us", /* MACHINE_UNKNOWN */ + "Your party is refusing messages", /* PERMISSION_REFUSED */ + "Target machine can not handle remote talk", /* UNKNOWN_REQUEST */ + "Target machine indicates protocol mismatch", /* BADVERSION */ + "Target machine indicates protocol botch (addr)",/* BADADDR */ + "Target machine indicates protocol botch (ctl_addr)",/* BADCTLADDR */ +}; +#define NANSWERS (sizeof (answers) / sizeof (answers[0])) + +/* + * Transmit the invitation and process the response + */ +announce_invite() +{ + CTL_RESPONSE response; + + current_state = "Trying to connect to your party's talk daemon"; + ctl_transact(his_machine_addr, msg, ANNOUNCE, &response); + remote_id = response.id_num; + if (response.answer != SUCCESS) { + if (response.answer < NANSWERS) + message(answers[response.answer]); + quit(); + } + /* leave the actual invitation on my talk daemon */ + ctl_transact(my_machine_addr, msg, LEAVE_INVITE, &response); + local_id = response.id_num; +} + +/* + * Tell the daemon to remove your invitation + */ +send_delete() +{ + + msg.type = DELETE; + /* + * This is just a extra clean up, so just send it + * and don't wait for an answer + */ + msg.id_num = htonl(remote_id); + daemon_addr.sin_addr = his_machine_addr; + if (sendto(ctl_sockt, &msg, sizeof (msg), 0, + (struct sockaddr *)&daemon_addr, + sizeof (daemon_addr)) != sizeof(msg)) + perror("send_delete (remote)"); + msg.id_num = htonl(local_id); + daemon_addr.sin_addr = my_machine_addr; + if (sendto(ctl_sockt, &msg, sizeof (msg), 0, + (struct sockaddr *)&daemon_addr, + sizeof (daemon_addr)) != sizeof (msg)) + perror("send_delete (local)"); +} diff --git a/talk.tproj/io.c b/talk.tproj/io.c new file mode 100644 index 0000000..efd3c30 --- /dev/null +++ b/talk.tproj/io.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * This file contains the I/O handling and the exchange of + * edit characters. This connection itself is established in + * ctl.c + */ + +#include +#include +#include +#include +#include +#include "talk.h" + +#define A_LONG_TIME 10000000 +#define STDIN_MASK (1< +#include +#include +#include +#include +#include "talk_ctl.h" +#include "talk.h" + +/* + * See if the local daemon has an invitation for us. + */ +check_local() +{ + CTL_RESPONSE response; + register CTL_RESPONSE *rp = &response; + + /* the rest of msg was set up in get_names */ +#ifdef MSG_EOR + /* copy new style sockaddr to old, swap family (short in old) */ + msg.ctl_addr = *(struct osockaddr *)&ctl_addr; + msg.ctl_addr.sa_family = htons(ctl_addr.sin_family); +#else + msg.ctl_addr = *(struct sockaddr *)&ctl_addr; +#endif + /* must be initiating a talk */ + if (!look_for_invite(rp)) + return (0); + /* + * There was an invitation waiting for us, + * so connect with the other (hopefully waiting) party + */ + current_state = "Waiting to connect with caller"; + do { + if (rp->addr.sa_family != AF_INET) + p_error("Response uses invalid network address"); + errno = 0; + if (connect(sockt, + (struct sockaddr *)&rp->addr, sizeof (rp->addr)) != -1) + return (1); + } while (errno == EINTR); + if (errno == ECONNREFUSED) { + /* + * The caller gave up, but his invitation somehow + * was not cleared. Clear it and initiate an + * invitation. (We know there are no newer invitations, + * the talkd works LIFO.) + */ + ctl_transact(his_machine_addr, msg, DELETE, rp); + close(sockt); + open_sockt(); + return (0); + } + p_error("Unable to connect with initiator"); + /*NOTREACHED*/ +} + +/* + * Look for an invitation on 'machine' + */ +look_for_invite(rp) + CTL_RESPONSE *rp; +{ + struct in_addr machine_addr; + + current_state = "Checking for invitation on caller's machine"; + ctl_transact(his_machine_addr, msg, LOOK_UP, rp); + /* the switch is for later options, such as multiple invitations */ + switch (rp->answer) { + + case SUCCESS: + msg.id_num = htonl(rp->id_num); + return (1); + + default: + /* there wasn't an invitation waiting for us */ + return (0); + } +} diff --git a/talk.tproj/msgs.c b/talk.tproj/msgs.c new file mode 100644 index 0000000..7e1edb1 --- /dev/null +++ b/talk.tproj/msgs.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* + * A package to display what is happening every MSG_INTERVAL seconds + * if we are slow connecting. + */ + +#include +#include +#include +#include "talk.h" + +#define MSG_INTERVAL 4 + +char *current_state; +int current_line = 0; + +void +disp_msg() +{ + message(current_state); +} + +start_msgs() +{ + struct itimerval itimer; + + message(current_state); + signal(SIGALRM, disp_msg); + itimer.it_value.tv_sec = itimer.it_interval.tv_sec = MSG_INTERVAL; + itimer.it_value.tv_usec = itimer.it_interval.tv_usec = 0; + setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); +} + +end_msgs() +{ + struct itimerval itimer; + + timerclear(&itimer.it_value); + timerclear(&itimer.it_interval); + setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); + signal(SIGALRM, SIG_DFL); +} diff --git a/talk.tproj/talk.1 b/talk.tproj/talk.1 new file mode 100644 index 0000000..18c3304 --- /dev/null +++ b/talk.tproj/talk.1 @@ -0,0 +1,129 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)talk.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt TALK 1 +.Os BSD 4.2 +.Sh NAME +.Nm talk +.Nd talk to another user +.Sh SYNOPSIS +.Nm talk +.Ar person +.Op Ar ttyname +.Sh DESCRIPTION +.Nm Talk +is a visual communication program which copies lines from your +terminal to that of another user. +.Pp +Options available: +.Bl -tag -width ttyname +.It Ar person +If you wish to talk to someone on your own machine, then +.Ar person +is just the person's login name. If you wish to talk to a user on +another host, then +.Ar person +is of the form +.Ql user@host . +.It Ar ttyname +If you wish to talk to a user who is logged in more than once, the +.Ar ttyname +argument may be used to indicate the appropriate terminal +name, where +.Ar ttyname +is of the form +.Ql ttyXX . +.El +.Pp +When first called, +.Nm talk +sends the message +.Bd -literal -offset indent -compact +Message from TalkDaemon@his_machine... +talk: connection requested by your_name@your_machine. +talk: respond with: talk your_name@your_machine +.Ed +.Pp +to the user you wish to talk to. At this point, the recipient +of the message should reply by typing +.Pp +.Dl talk \ your_name@your_machine +.Pp +It doesn't matter from which machine the recipient replies, as +long as his login-name is the same. Once communication is established, +the two parties may type simultaneously, with their output appearing +in separate windows. Typing control-L +.Ql ^L +will cause the screen to +be reprinted, while your erase, kill, and word kill characters will +behave normally. To exit, just type your interrupt character; +.Nm talk +then moves the cursor to the bottom of the screen and restores the +terminal to its previous state. +.Pp +Permission to talk may be denied or granted by use of the +.Xr mesg 1 +command. At the outset talking is allowed. Certain commands, in +particular +.Xr nroff 1 +and +.Xr pr 1 , +disallow messages in order to +prevent messy output. +.Pp +.Sh FILES +.Bl -tag -width /var/run/utmp -compact +.It Pa /etc/hosts +to find the recipient's machine +.It Pa /var/run/utmp +to find the recipient's tty +.El +.Sh SEE ALSO +.Xr mail 1 , +.Xr mesg 1 , +.Xr who 1 , +.Xr write 1 +.Sh BUGS +The version of +.Xr talk 1 +released with +.Bx 4.3 +uses a protocol that +is incompatible with the protocol used in the version released with +.Bx 4.2 . +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/talk.tproj/talk.c b/talk.tproj/talk.c new file mode 100644 index 0000000..3690d01 --- /dev/null +++ b/talk.tproj/talk.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#include "talk.h" + +/* + * talk: A visual form of write. Using sockets, a two way + * connection is set up between the two people talking. + * With the aid of curses, the screen is split into two + * windows, and each users text is added to the window, + * one character at a time... + * + * Written by Kipp Hickman + * + * Modified to run under 4.1a by Clem Cole and Peter Moore + * Modified to run between hosts by Peter Moore, 8/19/82 + * Modified to run under 4.1c by Peter Moore 3/17/83 + */ + +main(argc, argv) + int argc; + char *argv[]; +{ + get_names(argc, argv); + init_display(); + open_ctl(); + open_sockt(); + start_msgs(); + if (!check_local()) + invite_remote(); + end_msgs(); + set_edit_chars(); + talk(); +} diff --git a/talk.tproj/talk.h b/talk.tproj/talk.h new file mode 100644 index 0000000..2458247 --- /dev/null +++ b/talk.tproj/talk.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)talk.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +extern int sockt; +extern int curses_initialized; +extern int invitation_waiting; + +extern char *current_state; +extern int current_line; + +typedef struct xwin { + WINDOW *x_win; + int x_nlines; + int x_ncols; + int x_line; + int x_col; + char kill; + char cerase; + char werase; +} xwin_t; + +extern xwin_t my_win; +extern xwin_t his_win; +extern WINDOW *line_win; diff --git a/talk.tproj/talk_ctl.h b/talk.tproj/talk_ctl.h new file mode 100644 index 0000000..bfe8416 --- /dev/null +++ b/talk.tproj/talk_ctl.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)talk_ctl.h 8.1 (Berkeley) 6/6/93 + */ + +extern struct sockaddr_in daemon_addr; +extern struct sockaddr_in ctl_addr; +extern struct sockaddr_in my_addr; +extern struct in_addr my_machine_addr; +extern struct in_addr his_machine_addr; +extern u_short daemon_port; +extern int ctl_sockt; +extern CTL_MSG msg; diff --git a/talkd.tproj/Makefile b/talkd.tproj/Makefile new file mode 100644 index 0000000..e727fa6 --- /dev/null +++ b/talkd.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ntalkd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = talkd.h + +CFILES = announce.c print.c process.c table.c talkd.c + +OTHERSRCS = Makefile Makefile.dist Makefile.postamble Makefile.preamble\ + talkd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/talkd.tproj/Makefile.dist b/talkd.tproj/Makefile.dist new file mode 100644 index 0000000..51f6806 --- /dev/null +++ b/talkd.tproj/Makefile.dist @@ -0,0 +1,8 @@ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 + +PROG= ntalkd +SRCS= talkd.c announce.c process.c table.c print.c ttymsg.c +.PATH: ${.CURDIR}/../../usr.bin/wall +MAN8= talkd.0 + +.include diff --git a/talkd.tproj/Makefile.postamble b/talkd.tproj/Makefile.postamble new file mode 100644 index 0000000..9d4f92c --- /dev/null +++ b/talkd.tproj/Makefile.postamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + +VPATH += :../wall.tproj + diff --git a/talkd.tproj/Makefile.preamble b/talkd.tproj/Makefile.preamble new file mode 100644 index 0000000..9764639 --- /dev/null +++ b/talkd.tproj/Makefile.preamble @@ -0,0 +1,120 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES= ttymsg.o +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +OTHER_OFILES = ttymsg.o +-include ../Makefile.include diff --git a/talkd.tproj/PB.project b/talkd.tproj/PB.project new file mode 100644 index 0000000..15be3ec --- /dev/null +++ b/talkd.tproj/PB.project @@ -0,0 +1,39 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (talkd.h); + M_FILES = (); + OTHER_LINKED = (announce.c, print.c, process.c, table.c, talkd.c); + OTHER_SOURCES = (Makefile, Makefile.dist, Makefile.postamble, Makefile.preamble, talkd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ntalkd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/talkd.tproj/announce.c b/talkd.tproj/announce.c new file mode 100644 index 0000000..cda84a1 --- /dev/null +++ b/talkd.tproj/announce.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)announce.c 8.3 (Berkeley) 1/7/94"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "talkd.h" + +extern char hostname[]; + +int print_mesg __P((char *tty, CTL_MSG *request, char *remote_machine)); + +/* + * Announce an invitation to talk. + */ + +/* + * See if the user is accepting messages. If so, announce that + * a talk is requested. + */ +int +announce(request, remote_machine) + CTL_MSG *request; + char *remote_machine; +{ + char full_tty[32]; + struct stat stbuf; + + (void)snprintf(full_tty, sizeof(full_tty), + "%s%s", _PATH_DEV, request->r_tty); + if (stat(full_tty, &stbuf) < 0 || (stbuf.st_mode&020) == 0) + return (PERMISSION_DENIED); + return (print_mesg(request->r_tty, request, remote_machine)); +} + +#define max(a,b) ( (a) > (b) ? (a) : (b) ) +#define N_LINES 5 +#define N_CHARS 256 + +/* + * Build a block of characters containing the message. + * It is sent blank filled and in a single block to + * try to keep the message in one piece if the recipient + * in in vi at the time + */ +int +print_mesg(tty, request, remote_machine) + char *tty; + CTL_MSG *request; + char *remote_machine; +{ + struct timeval clock; + struct timezone zone; + struct tm *localtime(); + struct tm *localclock; + struct iovec iovec; + char line_buf[N_LINES][N_CHARS]; + int sizes[N_LINES]; + char big_buf[N_LINES*N_CHARS]; + char *bptr, *lptr, *vis_user; + int i, j, max_size; + + i = 0; + max_size = 0; + gettimeofday(&clock, &zone); + localclock = localtime( &clock.tv_sec ); + (void)snprintf(line_buf[i], N_CHARS, " "); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + (void)snprintf(line_buf[i], N_CHARS, + "Message from Talk_Daemon@%s at %d:%02d ...", + hostname, localclock->tm_hour , localclock->tm_min ); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + + vis_user = malloc(strlen(request->l_name) * 4 + 1); + strvis(vis_user, request->l_name, VIS_CSTYLE); + (void)snprintf(line_buf[i], N_CHARS, + "talk: connection requested by %s@%s", vis_user, remote_machine); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + (void)snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s", + vis_user, remote_machine); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + (void)snprintf(line_buf[i], N_CHARS, " "); + sizes[i] = strlen(line_buf[i]); + max_size = max(max_size, sizes[i]); + i++; + bptr = big_buf; + *bptr++ = ''; /* send something to wake them up */ + *bptr++ = '\r'; /* add a \r in case of raw mode */ + *bptr++ = '\n'; + for (i = 0; i < N_LINES; i++) { + /* copy the line into the big buffer */ + lptr = line_buf[i]; + while (*lptr != '\0') + *(bptr++) = *(lptr++); + /* pad out the rest of the lines with blanks */ + for (j = sizes[i]; j < max_size + 2; j++) + *(bptr++) = ' '; + *(bptr++) = '\r'; /* add a \r in case of raw mode */ + *(bptr++) = '\n'; + } + *bptr = '\0'; + iovec.iov_base = big_buf; + iovec.iov_len = bptr - big_buf; + /* + * we choose a timeout of RING_WAIT-5 seconds so that we don't + * stack up processes trying to write messages to a tty + * that is permanently blocked. + */ + if (ttymsg(&iovec, 1, tty, RING_WAIT - 5) != NULL) + return (FAILED); + + return (SUCCESS); +} diff --git a/talkd.tproj/print.c b/talkd.tproj/print.c new file mode 100644 index 0000000..74f7aa8 --- /dev/null +++ b/talkd.tproj/print.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)print.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* debug print routines */ + +#include +#include +#include +#include +#include + +static char *types[] = + { "leave_invite", "look_up", "delete", "announce" }; +#define NTYPES (sizeof (types) / sizeof (types[0])) +static char *answers[] = + { "success", "not_here", "failed", "machine_unknown", "permission_denied", + "unknown_request", "badversion", "badaddr", "badctladdr" }; +#define NANSWERS (sizeof (answers) / sizeof (answers[0])) + +void +print_request(cp, mp) + char *cp; + register CTL_MSG *mp; +{ + char tbuf[80], *tp; + + if (mp->type > NTYPES) { + (void)sprintf(tbuf, "type %d", mp->type); + tp = tbuf; + } else + tp = types[mp->type]; + syslog(LOG_DEBUG, "%s: %s: id %d, l_user %s, r_user %s, r_tty %s", + cp, tp, mp->id_num, mp->l_name, mp->r_name, mp->r_tty); +} + +void +print_response(cp, rp) + char *cp; + register CTL_RESPONSE *rp; +{ + char tbuf[80], *tp, abuf[80], *ap; + + if (rp->type > NTYPES) { + (void)sprintf(tbuf, "type %d", rp->type); + tp = tbuf; + } else + tp = types[rp->type]; + if (rp->answer > NANSWERS) { + (void)sprintf(abuf, "answer %d", rp->answer); + ap = abuf; + } else + ap = answers[rp->answer]; + syslog(LOG_DEBUG, "%s: %s: %s, id %d", cp, tp, ap, ntohl(rp->id_num)); +} diff --git a/talkd.tproj/process.c b/talkd.tproj/process.c new file mode 100644 index 0000000..c7d7b2c --- /dev/null +++ b/talkd.tproj/process.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93"; +#endif /* not lint */ + +/* + * process.c handles the requests, which can be of three types: + * ANNOUNCE - announce to a user that a talk is wanted + * LEAVE_INVITE - insert the request into the table + * LOOK_UP - look up to see if a request is waiting in + * in the table for the local user + * DELETE - delete invitation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "talkd.h" + +CTL_MSG *find_request(); +CTL_MSG *find_match(); + +void +process_request(mp, rp) + register CTL_MSG *mp; + register CTL_RESPONSE *rp; +{ + register CTL_MSG *ptr; + extern int debug; + + rp->vers = TALK_VERSION; + rp->type = mp->type; + rp->id_num = htonl(0); + if (mp->vers != TALK_VERSION) { + syslog(LOG_WARNING, "Bad protocol version %d", mp->vers); + rp->answer = BADVERSION; + return; + } + mp->id_num = ntohl(mp->id_num); + mp->addr.sa_family = ntohs(mp->addr.sa_family); + if (mp->addr.sa_family != AF_INET) { + syslog(LOG_WARNING, "Bad address, family %d", + mp->addr.sa_family); + rp->answer = BADADDR; + return; + } + mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family); + if (mp->ctl_addr.sa_family != AF_INET) { + syslog(LOG_WARNING, "Bad control address, family %d", + mp->ctl_addr.sa_family); + rp->answer = BADCTLADDR; + return; + } + mp->pid = ntohl(mp->pid); + if (debug) + print_request("process_request", mp); + switch (mp->type) { + + case ANNOUNCE: + do_announce(mp, rp); + break; + + case LEAVE_INVITE: + ptr = find_request(mp); + if (ptr != (CTL_MSG *)0) { + rp->id_num = htonl(ptr->id_num); + rp->answer = SUCCESS; + } else + insert_table(mp, rp); + break; + + case LOOK_UP: + ptr = find_match(mp); + if (ptr != (CTL_MSG *)0) { + rp->id_num = htonl(ptr->id_num); + rp->addr = ptr->addr; + rp->addr.sa_family = htons(ptr->addr.sa_family); + rp->answer = SUCCESS; + } else + rp->answer = NOT_HERE; + break; + + case DELETE: + rp->answer = delete_invite(mp->id_num); + break; + + default: + rp->answer = UNKNOWN_REQUEST; + break; + } + if (debug) + print_response("process_request", rp); +} + +void +do_announce(mp, rp) + register CTL_MSG *mp; + CTL_RESPONSE *rp; +{ + struct hostent *hp; + CTL_MSG *ptr; + int result; + + /* see if the user is logged */ + result = find_user(mp->r_name, mp->r_tty); + if (result != SUCCESS) { + rp->answer = result; + return; + } +#define satosin(sa) ((struct sockaddr_in *)(sa)) + hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr, + sizeof (struct in_addr), AF_INET); + if (hp == (struct hostent *)0) { + rp->answer = MACHINE_UNKNOWN; + return; + } + ptr = find_request(mp); + if (ptr == (CTL_MSG *) 0) { + insert_table(mp, rp); + rp->answer = announce(mp, hp->h_name); + return; + } + if (mp->id_num > ptr->id_num) { + /* + * This is an explicit re-announce, so update the id_num + * field to avoid duplicates and re-announce the talk. + */ + ptr->id_num = new_id(); + rp->id_num = htonl(ptr->id_num); + rp->answer = announce(mp, hp->h_name); + } else { + /* a duplicated request, so ignore it */ + rp->id_num = htonl(ptr->id_num); + rp->answer = SUCCESS; + } +} + +#include + +/* + * Search utmp for the local user + */ +int +find_user(name, tty) + char *name, *tty; +{ + struct utmp ubuf; + int status; + FILE *fd; + struct stat statb; + char line[sizeof(ubuf.ut_line) + 1]; + char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)]; + + if ((fd = fopen(_PATH_UTMP, "r")) == NULL) { + fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP); + return (FAILED); + } +#define SCMPN(a, b) strncmp(a, b, sizeof (a)) + status = NOT_HERE; + (void) strcpy(ftty, _PATH_DEV); + while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1) + if (SCMPN(ubuf.ut_name, name) == 0) { + strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line)); + line[sizeof(ubuf.ut_line)] = '\0'; + if (*tty == '\0') { + status = PERMISSION_DENIED; + /* no particular tty was requested */ + (void) strcpy(ftty + sizeof(_PATH_DEV) - 1, + line); + if (stat(ftty, &statb) == 0) { + if (!(statb.st_mode & 020)) + continue; + (void) strcpy(tty, line); + status = SUCCESS; + break; + } + } + if (strcmp(line, tty) == 0) { + status = SUCCESS; + break; + } + } + fclose(fd); + return (status); +} diff --git a/talkd.tproj/table.c b/talkd.tproj/table.c new file mode 100644 index 0000000..df3fb23 --- /dev/null +++ b/talkd.tproj/table.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Routines to handle insertion, deletion, etc on the table + * of requests kept by the daemon. Nothing fancy here, linear + * search on a double-linked list. A time is kept with each + * entry so that overly old invitations can be eliminated. + * + * Consider this a mis-guided attempt at modularity + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "talkd.h" + +#define MAX_ID 16000 /* << 2^15 so I don't have sign troubles */ + +#define NIL ((TABLE_ENTRY *)0) + +extern int debug; +struct timeval tp; +struct timezone txp; + +typedef struct table_entry TABLE_ENTRY; + +struct table_entry { + CTL_MSG request; + long time; + TABLE_ENTRY *next; + TABLE_ENTRY *last; +}; + +TABLE_ENTRY *table = NIL; +CTL_MSG *find_request(); +CTL_MSG *find_match(); + +void delete __P((TABLE_ENTRY *ptr)); + +/* + * Look in the table for an invitation that matches the current + * request looking for an invitation + */ +CTL_MSG * +find_match(request) + register CTL_MSG *request; +{ + register TABLE_ENTRY *ptr; + time_t current_time; + + gettimeofday(&tp, &txp); + current_time = tp.tv_sec; + if (debug) + print_request("find_match", request); + for (ptr = table; ptr != NIL; ptr = ptr->next) { + if ((ptr->time - current_time) > MAX_LIFE) { + /* the entry is too old */ + if (debug) + print_request("deleting expired entry", + &ptr->request); + delete(ptr); + continue; + } + if (debug) + print_request("", &ptr->request); + if (strcmp(request->l_name, ptr->request.r_name) == 0 && + strcmp(request->r_name, ptr->request.l_name) == 0 && + ptr->request.type == LEAVE_INVITE) + return (&ptr->request); + } + return ((CTL_MSG *)0); +} + +/* + * Look for an identical request, as opposed to a complimentary + * one as find_match does + */ +CTL_MSG * +find_request(request) + register CTL_MSG *request; +{ + register TABLE_ENTRY *ptr; + time_t current_time; + + gettimeofday(&tp, &txp); + current_time = tp.tv_sec; + /* + * See if this is a repeated message, and check for + * out of date entries in the table while we are it. + */ + if (debug) + print_request("find_request", request); + for (ptr = table; ptr != NIL; ptr = ptr->next) { + if ((ptr->time - current_time) > MAX_LIFE) { + /* the entry is too old */ + if (debug) + print_request("deleting expired entry", + &ptr->request); + delete(ptr); + continue; + } + if (debug) + print_request("", &ptr->request); + if (strcmp(request->r_name, ptr->request.r_name) == 0 && + strcmp(request->l_name, ptr->request.l_name) == 0 && + request->type == ptr->request.type && + request->pid == ptr->request.pid) { + /* update the time if we 'touch' it */ + ptr->time = current_time; + return (&ptr->request); + } + } + return ((CTL_MSG *)0); +} + +void +insert_table(request, response) + CTL_MSG *request; + CTL_RESPONSE *response; +{ + register TABLE_ENTRY *ptr; + time_t current_time; + + gettimeofday(&tp, &txp); + current_time = tp.tv_sec; + request->id_num = new_id(); + response->id_num = htonl(request->id_num); + /* insert a new entry into the top of the list */ + ptr = (TABLE_ENTRY *)malloc(sizeof(TABLE_ENTRY)); + if (ptr == NIL) { + syslog(LOG_ERR, "insert_table: Out of memory"); + _exit(1); + } + ptr->time = current_time; + ptr->request = *request; + ptr->next = table; + if (ptr->next != NIL) + ptr->next->last = ptr; + ptr->last = NIL; + table = ptr; +} + +/* + * Generate a unique non-zero sequence number + */ +int +new_id() +{ + static int current_id = 0; + + current_id = (current_id + 1) % MAX_ID; + /* 0 is reserved, helps to pick up bugs */ + if (current_id == 0) + current_id = 1; + return (current_id); +} + +/* + * Delete the invitation with id 'id_num' + */ +int +delete_invite(id_num) + int id_num; +{ + register TABLE_ENTRY *ptr; + + ptr = table; + if (debug) + syslog(LOG_DEBUG, "delete_invite(%d)", id_num); + for (ptr = table; ptr != NIL; ptr = ptr->next) { + if (ptr->request.id_num == id_num) + break; + if (debug) + print_request("", &ptr->request); + } + if (ptr != NIL) { + delete(ptr); + return (SUCCESS); + } + return (NOT_HERE); +} + +/* + * Classic delete from a double-linked list + */ +void +delete(ptr) + register TABLE_ENTRY *ptr; +{ + + if (debug) + print_request("delete", &ptr->request); + if (table == ptr) + table = ptr->next; + else if (ptr->last != NIL) + ptr->last->next = ptr->next; + if (ptr->next != NIL) + ptr->next->last = ptr->last; + free((char *)ptr); +} diff --git a/talkd.tproj/talkd.8 b/talkd.tproj/talkd.8 new file mode 100644 index 0000000..36dfb28 --- /dev/null +++ b/talkd.tproj/talkd.8 @@ -0,0 +1,75 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)talkd.8 8.2 (Berkeley) 12/11/93 +.\" +.Dd December 11, 1993 +.Dt TALKD 8 +.Os BSD 4.3 +.Sh NAME +.Nm talkd +.Nd remote user communication server +.Sh SYNOPSIS +.Nm talkd +.Sh DESCRIPTION +.Nm Talkd +is the server that notifies a user that someone else wants to +initiate a conversation. +It acts as a repository of invitations, responding to requests +by clients wishing to rendezvous to hold a conversation. +In normal operation, a client, the caller, +initiates a rendezvous by sending a +.Tn CTL_MSG +to the server of +type +.Tn LOOK_UP +(see +.Aq Pa protocols/talkd.h ) . +This causes the server to search its invitation +tables to check if an invitation currently exists for the caller +(to speak to the callee specified in the message). +If the lookup fails, +the caller then sends an +.Tn ANNOUNCE +message causing the server to +broadcast an announcement on the callee's login ports requesting contact. +When the callee responds, the local server uses the +recorded invitation to respond with the appropriate rendezvous +address and the caller and callee client programs establish a +stream connection through which the conversation takes place. +.Sh SEE ALSO +.Xr talk 1 , +.Xr write 1 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/talkd.tproj/talkd.c b/talkd.tproj/talkd.c new file mode 100644 index 0000000..7281351 --- /dev/null +++ b/talkd.tproj/talkd.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)talkd.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * The top level of the daemon, the format is heavily borrowed + * from rwhod.c. Basically: find out who and where you are; + * disconnect all descriptors and ttys, and then endless + * loop on waiting for and processing requests + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "talkd.h" + +CTL_MSG request; +CTL_RESPONSE response; + +int sockt; +int debug = 0; +void timeout(); +long lastmsgtime; + +char hostname[MAXHOSTNAMELEN + 1]; + +#define TIMEOUT 30 +#define MAXIDLE 120 + +void +main(argc, argv) + int argc; + char *argv[]; +{ + register CTL_MSG *mp = &request; + int cc; + + if (getuid()) { + fprintf(stderr, "%s: getuid: not super-user\n", argv[0]); + exit(1); + } + openlog("talkd", LOG_PID, LOG_DAEMON); + if (gethostname(hostname, sizeof (hostname) - 1) < 0) { + syslog(LOG_ERR, "gethostname: %m"); + _exit(1); + } + if (chdir(_PATH_DEV) < 0) { + syslog(LOG_ERR, "chdir: %s: %m", _PATH_DEV); + _exit(1); + } + if (argc > 1 && strcmp(argv[1], "-d") == 0) + debug = 1; + signal(SIGALRM, timeout); + alarm(TIMEOUT); + for (;;) { + extern int errno; + + cc = recv(0, (char *)mp, sizeof (*mp), 0); + if (cc != sizeof (*mp)) { + if (cc < 0 && errno != EINTR) + syslog(LOG_WARNING, "recv: %m"); + continue; + } + lastmsgtime = time(0); + process_request(mp, &response); + /* can block here, is this what I want? */ + cc = sendto(sockt, (char *)&response, + sizeof (response), 0, (struct sockaddr *)&mp->ctl_addr, + sizeof (mp->ctl_addr)); + if (cc != sizeof (response)) + syslog(LOG_WARNING, "sendto: %m"); + } +} + +void +timeout() +{ + + if (time(0) - lastmsgtime >= MAXIDLE) + _exit(0); + alarm(TIMEOUT); +} diff --git a/talkd.tproj/talkd.h b/talkd.tproj/talkd.h new file mode 100644 index 0000000..9a686c5 --- /dev/null +++ b/talkd.tproj/talkd.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +extern int announce __P((CTL_MSG *request, char *remote_machine)); +extern void do_announce __P((CTL_MSG *mp, CTL_RESPONSE *rp)); +extern int delete_invite __P((int id_num)); +extern int find_user __P((char *name, char *tty)); +extern void insert_table __P((CTL_MSG *request, CTL_RESPONSE *response)); +extern int new_id __P((void)); +extern void print_request __P((char *cp, CTL_MSG *mp)); +extern void print_response __P((char *cp, CTL_RESPONSE *rp)); +extern void process_request __P((CTL_MSG *mp, CTL_RESPONSE *rp)); diff --git a/tcpdump.tproj/Makefile b/tcpdump.tproj/Makefile new file mode 100644 index 0000000..fb9c458 --- /dev/null +++ b/tcpdump.tproj/Makefile @@ -0,0 +1,63 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = tcpdump + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = machdep.h addrtoname.h ntp.h nfsfh.h igrp.h interface.h\ + os-sunos4.h decnet.h ipx.h mib.h os-ultrix4.h netbios.h\ + bootp.h ospf.h llc.h nfs.h os-solaris2.h nfsv2.h fddi.h\ + gnuc.h ethertype.h extract.h appletalk.h + +CFILES = addrtoname.c bpf_dump.c machdep.c parsenfsfh.c print-arp.c\ + print-atalk.c print-atm.c print-bootp.c print-decnet.c\ + print-domain.c print-dvmrp.c print-egp.c print-ether.c\ + print-fddi.c print-gre.c print-icmp.c print-igrp.c print-ip.c\ + print-ipx.c print-isoclns.c print-krb.c print-llc.c\ + print-netbios.c print-nfs.c print-ntp.c print-null.c\ + print-ospf.c print-pim.c print-ppp.c print-rip.c print-skip.c\ + print-sl.c print-snmp.c print-sunrpc.c print-tcp.c\ + print-tftp.c print-udp.c print-wb.c strcasecmp.c tcpdump.c\ + util.c version.c vfprintf.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = -lpcap +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -traditional-cpp + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/tcpdump.tproj/Makefile.postamble b/tcpdump.tproj/Makefile.postamble new file mode 100644 index 0000000..7823726 --- /dev/null +++ b/tcpdump.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/tcpdump.tproj/Makefile.preamble b/tcpdump.tproj/Makefile.preamble new file mode 100644 index 0000000..faec713 --- /dev/null +++ b/tcpdump.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS =-DRETSIGTYPE=void +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/tcpdump.tproj/PB.project b/tcpdump.tproj/PB.project new file mode 100644 index 0000000..143e686 --- /dev/null +++ b/tcpdump.tproj/PB.project @@ -0,0 +1,98 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + CLASSES = (); + FRAMEWORKS = (); + H_FILES = ( + machdep.h, + addrtoname.h, + ntp.h, + nfsfh.h, + igrp.h, + interface.h, + "os-sunos4.h", + decnet.h, + ipx.h, + mib.h, + "os-ultrix4.h", + netbios.h, + bootp.h, + ospf.h, + llc.h, + nfs.h, + "os-solaris2.h", + nfsv2.h, + fddi.h, + gnuc.h, + ethertype.h, + extract.h, + appletalk.h + ); + OTHER_LIBS = (pcap); + OTHER_LINKED = ( + addrtoname.c, + bpf_dump.c, + machdep.c, + parsenfsfh.c, + "print-arp.c", + "print-atalk.c", + "print-atm.c", + "print-bootp.c", + "print-decnet.c", + "print-domain.c", + "print-dvmrp.c", + "print-egp.c", + "print-ether.c", + "print-fddi.c", + "print-gre.c", + "print-icmp.c", + "print-igrp.c", + "print-ip.c", + "print-ipx.c", + "print-isoclns.c", + "print-krb.c", + "print-llc.c", + "print-netbios.c", + "print-nfs.c", + "print-ntp.c", + "print-null.c", + "print-ospf.c", + "print-pim.c", + "print-ppp.c", + "print-rip.c", + "print-skip.c", + "print-sl.c", + "print-snmp.c", + "print-sunrpc.c", + "print-tcp.c", + "print-tftp.c", + "print-udp.c", + "print-wb.c", + strcasecmp.c, + tcpdump.c, + util.c, + version.c, + vfprintf.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-traditional-cpp"; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = tcpdump; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/tcpdump.tproj/addrtoname.c b/tcpdump.tproj/addrtoname.c new file mode 100644 index 0000000..f940348 --- /dev/null +++ b/tcpdump.tproj/addrtoname.c @@ -0,0 +1,779 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Internet, ethernet, port, and protocol string to address + * and address to string conversion routines + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/addrtoname.c,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "llc.h" + +/* Forwards */ +static RETSIGTYPE nohostname(int); + +/* + * hash tables for whatever-to-name translations + */ + +#define HASHNAMESIZE 4096 + +struct hnamemem { + u_int32_t addr; + char *name; + struct hnamemem *nxt; +}; + +struct hnamemem hnametable[HASHNAMESIZE]; +struct hnamemem tporttable[HASHNAMESIZE]; +struct hnamemem uporttable[HASHNAMESIZE]; +struct hnamemem eprototable[HASHNAMESIZE]; +struct hnamemem dnaddrtable[HASHNAMESIZE]; +struct hnamemem llcsaptable[HASHNAMESIZE]; + +struct enamemem { + u_short e_addr0; + u_short e_addr1; + u_short e_addr2; + char *e_name; + u_char *e_nsap; /* used only for nsaptable[] */ + struct enamemem *e_nxt; +}; + +struct enamemem enametable[HASHNAMESIZE]; +struct enamemem nsaptable[HASHNAMESIZE]; + +struct protoidmem { + u_int32_t p_oui; + u_short p_proto; + char *p_name; + struct protoidmem *p_nxt; +}; + +struct protoidmem protoidtable[HASHNAMESIZE]; + +/* + * A faster replacement for inet_ntoa(). + */ +char * +intoa(u_int32_t addr) +{ + register char *cp; + register u_int byte; + register int n; + static char buf[sizeof(".xxx.xxx.xxx.xxx")]; + + NTOHL(addr); + cp = &buf[sizeof buf]; + *--cp = '\0'; + + n = 4; + do { + byte = addr & 0xff; + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) { + *--cp = byte % 10 + '0'; + byte /= 10; + if (byte > 0) + *--cp = byte + '0'; + } + *--cp = '.'; + addr >>= 8; + } while (--n > 0); + + return cp + 1; +} + +static u_int32_t f_netmask; +static u_int32_t f_localnet; +static u_int32_t netmask; + +/* + * "getname" is written in this atrocious way to make sure we don't + * wait forever while trying to get hostnames from yp. + */ +#include + +jmp_buf getname_env; + +static RETSIGTYPE +nohostname(int signo) +{ + longjmp(getname_env, 1); +} + +/* + * Return a name for the IP address pointed to by ap. This address + * is assumed to be in network byte order. + */ +char * +getname(const u_char *ap) +{ + register struct hostent *hp; + u_int32_t addr; + static struct hnamemem *p; /* static for longjmp() */ + +#ifndef LBL_ALIGN + addr = *(const u_int32_t *)ap; +#else + /* + * Extract 32 bits in network order, dealing with alignment. + */ + switch ((long)ap & 3) { + + case 0: + addr = *(u_int32_t *)ap; + break; + + case 2: +#ifdef WORDS_BIGENDIAN + addr = ((u_int32_t)*(u_short *)ap << 16) | + (u_int32_t)*(u_short *)(ap + 2); +#else + addr = ((u_int32_t)*(u_short *)(ap + 2) << 16) | + (u_int32_t)*(u_short *)ap; +#endif + break; + + default: +#ifdef WORDS_BIGENDIAN + addr = ((u_int32_t)ap[0] << 24) | + ((u_int32_t)ap[1] << 16) | + ((u_int32_t)ap[2] << 8) | + (u_int32_t)ap[3]; +#else + addr = ((u_int32_t)ap[3] << 24) | + ((u_int32_t)ap[2] << 16) | + ((u_int32_t)ap[1] << 8) | + (u_int32_t)ap[0]; +#endif + break; + } +#endif + p = &hnametable[addr & (HASHNAMESIZE-1)]; + for (; p->nxt; p = p->nxt) { + if (p->addr == addr) + return (p->name); + } + p->addr = addr; + p->nxt = newhnamemem(); + + /* + * Only print names when: + * (1) -n was not given. + * (2) Address is foreign and -f was given. If -f was not + * present, f_netmask and f_local are 0 and the second + * test will succeed. + * (3) The host portion is not 0 (i.e., a network address). + * (4) The host portion is not broadcast. + */ + if (!nflag && (addr & f_netmask) == f_localnet + && (addr &~ netmask) != 0 && (addr | netmask) != 0xffffffff) { + if (!setjmp(getname_env)) { + (void)signal(SIGALRM, nohostname); + (void)alarm(20); + hp = gethostbyaddr((char *)&addr, 4, AF_INET); + (void)alarm(0); + if (hp) { + char *dotp; + + p->name = savestr(hp->h_name); + if (Nflag) { + /* Remove domain qualifications */ + dotp = strchr(p->name, '.'); + if (dotp) + *dotp = '\0'; + } + return (p->name); + } + } + } + p->name = savestr(intoa(addr)); + return (p->name); +} + +static char hex[] = "0123456789abcdef"; + + +/* Find the hash node that corresponds the ether address 'ep' */ + +static inline struct enamemem * +lookup_emem(const u_char *ep) +{ + register u_int i, j, k; + struct enamemem *tp; + + k = (ep[0] << 8) | ep[1]; + j = (ep[2] << 8) | ep[3]; + i = (ep[4] << 8) | ep[5]; + + tp = &enametable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->e_nxt) + if (tp->e_addr0 == i && + tp->e_addr1 == j && + tp->e_addr2 == k) + return tp; + else + tp = tp->e_nxt; + tp->e_addr0 = i; + tp->e_addr1 = j; + tp->e_addr2 = k; + tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); + if (tp->e_nxt == NULL) + error("lookup_emem: calloc"); + + return tp; +} + +/* Find the hash node that corresponds the NSAP 'nsap' */ + +static inline struct enamemem * +lookup_nsap(register const u_char *nsap) +{ + register u_int i, j, k; + int nlen = *nsap; + struct enamemem *tp; + const u_char *ensap = nsap + nlen - 6; + + if (nlen > 6) { + k = (ensap[0] << 8) | ensap[1]; + j = (ensap[2] << 8) | ensap[3]; + i = (ensap[4] << 8) | ensap[5]; + } + else + i = j = k = 0; + + tp = &nsaptable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->e_nxt) + if (tp->e_addr0 == i && + tp->e_addr1 == j && + tp->e_addr2 == k && + tp->e_nsap[0] == nlen && + memcmp((char *)&(nsap[1]), + (char *)&(tp->e_nsap[1]), nlen) == 0) + return tp; + else + tp = tp->e_nxt; + tp->e_addr0 = i; + tp->e_addr1 = j; + tp->e_addr2 = k; + tp->e_nsap = (u_char *)malloc(nlen + 1); + if (tp->e_nsap == NULL) + error("lookup_nsap: malloc"); + memcpy(tp->e_nsap, nsap, nlen + 1); + tp->e_nxt = (struct enamemem *)calloc(1, sizeof(*tp)); + if (tp->e_nxt == NULL) + error("lookup_nsap: calloc"); + + return tp; +} + +/* Find the hash node that corresponds the protoid 'pi'. */ + +static inline struct protoidmem * +lookup_protoid(const u_char *pi) +{ + register u_int i, j; + struct protoidmem *tp; + + /* 5 octets won't be aligned */ + i = (((pi[0] << 8) + pi[1]) << 8) + pi[2]; + j = (pi[3] << 8) + pi[4]; + /* XXX should be endian-insensitive, but do big-endian testing XXX */ + + tp = &protoidtable[(i ^ j) & (HASHNAMESIZE-1)]; + while (tp->p_nxt) + if (tp->p_oui == i && tp->p_proto == j) + return tp; + else + tp = tp->p_nxt; + tp->p_oui = i; + tp->p_proto = j; + tp->p_nxt = (struct protoidmem *)calloc(1, sizeof(*tp)); + if (tp->p_nxt == NULL) + error("lookup_protoid: calloc"); + + return tp; +} + +char * +etheraddr_string(register const u_char *ep) +{ + register u_int i, j; + register char *cp; + register struct enamemem *tp; + char buf[sizeof("00:00:00:00:00:00")]; + + tp = lookup_emem(ep); + if (tp->e_name) + return (tp->e_name); +#ifdef HAVE_ETHER_NTOHOST + if (!nflag) { + char buf[128]; + if (ether_ntohost(buf, (struct ether_addr *)ep) == 0) { + tp->e_name = savestr(buf); + return (tp->e_name); + } + } +#endif + cp = buf; + if ((j = *ep >> 4) != 0) + *cp++ = hex[j]; + *cp++ = hex[*ep++ & 0xf]; + for (i = 5; (int)--i >= 0;) { + *cp++ = ':'; + if ((j = *ep >> 4) != 0) + *cp++ = hex[j]; + *cp++ = hex[*ep++ & 0xf]; + } + *cp = '\0'; + tp->e_name = savestr(buf); + return (tp->e_name); +} + +char * +etherproto_string(u_short port) +{ + register char *cp; + register struct hnamemem *tp; + register u_int32_t i = port; + char buf[sizeof("0000")]; + + for (tp = &eprototable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->addr = i; + tp->nxt = newhnamemem(); + + cp = buf; + NTOHS(port); + *cp++ = hex[port >> 12 & 0xf]; + *cp++ = hex[port >> 8 & 0xf]; + *cp++ = hex[port >> 4 & 0xf]; + *cp++ = hex[port & 0xf]; + *cp++ = '\0'; + tp->name = savestr(buf); + return (tp->name); +} + +char * +protoid_string(register const u_char *pi) +{ + register u_int i, j; + register char *cp; + register struct protoidmem *tp; + char buf[sizeof("00:00:00:00:00")]; + + tp = lookup_protoid(pi); + if (tp->p_name) + return tp->p_name; + + cp = buf; + if ((j = *pi >> 4) != 0) + *cp++ = hex[j]; + *cp++ = hex[*pi++ & 0xf]; + for (i = 4; (int)--i >= 0;) { + *cp++ = ':'; + if ((j = *pi >> 4) != 0) + *cp++ = hex[j]; + *cp++ = hex[*pi++ & 0xf]; + } + *cp = '\0'; + tp->p_name = savestr(buf); + return (tp->p_name); +} + +char * +llcsap_string(u_char sap) +{ + register char *cp; + register struct hnamemem *tp; + register u_int32_t i = sap; + char buf[sizeof("sap 00")]; + + for (tp = &llcsaptable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->addr = i; + tp->nxt = newhnamemem(); + + cp = buf; + (void)strcpy(cp, "sap "); + cp += strlen(cp); + *cp++ = hex[sap >> 4 & 0xf]; + *cp++ = hex[sap & 0xf]; + *cp++ = '\0'; + tp->name = savestr(buf); + return (tp->name); +} + +char * +isonsap_string(const u_char *nsap) +{ + register u_int i, nlen = nsap[0]; + register char *cp; + register struct enamemem *tp; + + tp = lookup_nsap(nsap); + if (tp->e_name) + return tp->e_name; + + tp->e_name = cp = (char *)malloc(nlen * 2 + 2); + if (cp == NULL) + error("isonsap_string: malloc"); + + nsap++; + *cp++ = '/'; + for (i = nlen; (int)--i >= 0;) { + *cp++ = hex[*nsap >> 4]; + *cp++ = hex[*nsap++ & 0xf]; + } + *cp = '\0'; + return (tp->e_name); +} + +char * +tcpport_string(u_short port) +{ + register struct hnamemem *tp; + register u_int32_t i = port; + char buf[sizeof("00000")]; + + for (tp = &tporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->addr = i; + tp->nxt = newhnamemem(); + + (void)sprintf(buf, "%u", i); + tp->name = savestr(buf); + return (tp->name); +} + +char * +udpport_string(register u_short port) +{ + register struct hnamemem *tp; + register u_int32_t i = port; + char buf[sizeof("00000")]; + + for (tp = &uporttable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + tp->addr = i; + tp->nxt = newhnamemem(); + + (void)sprintf(buf, "%u", i); + tp->name = savestr(buf); + return (tp->name); +} + +static void +init_servarray(void) +{ + struct servent *sv; + register struct hnamemem *table; + register int i; + char buf[sizeof("0000000000")]; + + while ((sv = getservent()) != NULL) { + int port = ntohs(sv->s_port); + i = port & (HASHNAMESIZE-1); + if (strcmp(sv->s_proto, "tcp") == 0) + table = &tporttable[i]; + else if (strcmp(sv->s_proto, "udp") == 0) + table = &uporttable[i]; + else + continue; + + while (table->name) + table = table->nxt; + if (nflag) { + (void)sprintf(buf, "%d", port); + table->name = savestr(buf); + } else + table->name = savestr(sv->s_name); + table->addr = port; + table->nxt = newhnamemem(); + } + endservent(); +} + +/*XXX from libbpfc.a */ +extern struct eproto { + char *s; + u_short p; +} eproto_db[]; + +static void +init_eprotoarray(void) +{ + register int i; + register struct hnamemem *table; + + for (i = 0; eproto_db[i].s; i++) { + int j = ntohs(eproto_db[i].p) & (HASHNAMESIZE-1); + table = &eprototable[j]; + while (table->name) + table = table->nxt; + table->name = eproto_db[i].s; + table->addr = ntohs(eproto_db[i].p); + table->nxt = newhnamemem(); + } +} + +/* + * SNAP proto IDs with org code 0:0:0 are actually encapsulated Ethernet + * types. + */ +static void +init_protoidarray(void) +{ + register int i; + register struct protoidmem *tp; + u_char protoid[5]; + + protoid[0] = 0; + protoid[1] = 0; + protoid[2] = 0; + for (i = 0; eproto_db[i].s; i++) { + u_short etype = htons(eproto_db[i].p); + + memcpy((char *)&protoid[3], (char *)&etype, 2); + tp = lookup_protoid(protoid); + tp->p_name = savestr(eproto_db[i].s); + } +} + +static struct etherlist { + u_char addr[6]; + char *name; +} etherlist[] = { + {{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }, "Broadcast" }, + {{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, NULL } +}; + +/* + * Initialize the ethers hash table. We take two different approaches + * depending on whether or not the system provides the ethers name + * service. If it does, we just wire in a few names at startup, + * and etheraddr_string() fills in the table on demand. If it doesn't, + * then we suck in the entire /etc/ethers file at startup. The idea + * is that parsing the local file will be fast, but spinning through + * all the ethers entries via NIS & next_etherent might be very slow. + * + * XXX pcap_next_etherent doesn't belong in the pcap interface, but + * since the pcap module already does name-to-address translation, + * it's already does most of the work for the ethernet address-to-name + * translation, so we just pcap_next_etherent as a convenience. + */ +static void +init_etherarray(void) +{ + register struct etherlist *el; + register struct enamemem *tp; +#ifdef HAVE_ETHER_NTOHOST + char name[256]; +#else + register struct pcap_etherent *ep; + register FILE *fp; + + /* Suck in entire ethers file */ + fp = fopen(PCAP_ETHERS_FILE, "r"); + if (fp != NULL) { + while ((ep = pcap_next_etherent(fp)) != NULL) { + tp = lookup_emem(ep->addr); + tp->e_name = savestr(ep->name); + } + (void)fclose(fp); + } +#endif + + /* Hardwire some ethernet names */ + for (el = etherlist; el->name != NULL; ++el) { + tp = lookup_emem(el->addr); + /* Don't override existing name */ + if (tp->e_name != NULL) + continue; + +#ifdef HAVE_ETHER_NTOHOST + /* Use yp/nis version of name if available */ + if (ether_ntohost(name, (struct ether_addr *)el->addr) == 0) { + tp->e_name = savestr(name); + continue; + } +#endif + tp->e_name = el->name; + } +} + +static struct tok llcsap_db[] = { + { LLCSAP_NULL, "null" }, + { LLCSAP_8021B_I, "802.1b-gsap" }, + { LLCSAP_8021B_G, "802.1b-isap" }, + { LLCSAP_IP, "ip-sap" }, + { LLCSAP_PROWAYNM, "proway-nm" }, + { LLCSAP_8021D, "802.1d" }, + { LLCSAP_RS511, "eia-rs511" }, + { LLCSAP_ISO8208, "x.25/llc2" }, + { LLCSAP_PROWAY, "proway" }, + { LLCSAP_ISONS, "iso-clns" }, + { LLCSAP_GLOBAL, "global" }, + { 0, NULL } +}; + +static void +init_llcsaparray(void) +{ + register int i; + register struct hnamemem *table; + + for (i = 0; llcsap_db[i].s != NULL; i++) { + table = &llcsaptable[llcsap_db[i].v]; + while (table->name) + table = table->nxt; + table->name = llcsap_db[i].s; + table->addr = llcsap_db[i].v; + table->nxt = newhnamemem(); + } +} + +/* + * Initialize the address to name translation machinery. We map all + * non-local IP addresses to numeric addresses if fflag is true (i.e., + * to prevent blocking on the nameserver). localnet is the IP address + * of the local network. mask is its subnet mask. + */ +void +init_addrtoname(int fflag, u_int32_t localnet, u_int32_t mask) +{ + netmask = mask; + if (fflag) { + f_localnet = localnet; + f_netmask = mask; + } + if (nflag) + /* + * Simplest way to suppress names. + */ + return; + + init_etherarray(); + init_servarray(); + init_eprotoarray(); + init_llcsaparray(); + init_protoidarray(); +} + +char * +dnaddr_string(u_short dnaddr) +{ + register struct hnamemem *tp; + + for (tp = &dnaddrtable[dnaddr & (HASHNAMESIZE-1)]; tp->nxt != 0; + tp = tp->nxt) + if (tp->addr == dnaddr) + return (tp->name); + + tp->addr = dnaddr; + tp->nxt = newhnamemem(); + if (nflag) + tp->name = dnnum_string(dnaddr); + else + tp->name = dnname_string(dnaddr); + + return(tp->name); +} + +/* Return a zero'ed hnamemem struct and cuts down on calloc() overhead */ +struct hnamemem * +newhnamemem(void) +{ + register struct hnamemem *p; + static struct hnamemem *ptr = NULL; + static u_int num = 0; + + if (num <= 0) { + num = 64; + ptr = (struct hnamemem *)calloc(num, sizeof (*ptr)); + if (ptr == NULL) + error("newhnamemem: calloc"); + } + --num; + p = ptr++; + return (p); +} diff --git a/tcpdump.tproj/addrtoname.h b/tcpdump.tproj/addrtoname.h new file mode 100644 index 0000000..c40b03f --- /dev/null +++ b/tcpdump.tproj/addrtoname.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1992, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/addrtoname.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) + */ + +/* Name to address translation routines. */ + +extern char *etheraddr_string(const u_char *); +extern char *etherproto_string(u_short); +extern char *tcpport_string(u_short); +extern char *udpport_string(u_short); +extern char *getname(const u_char *); +extern char *intoa(u_int32_t); + +extern void init_addrtoname(int, u_int32_t, u_int32_t); +extern struct hnamemem *newhnamemem(void); + +#define ipaddr_string(p) getname((const u_char *)(p)) diff --git a/tcpdump.tproj/appletalk.h b/tcpdump.tproj/appletalk.h new file mode 100644 index 0000000..49690e7 --- /dev/null +++ b/tcpdump.tproj/appletalk.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * AppleTalk protocol formats (courtesy Bill Croft of Stanford/SUMEX). + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/appletalk.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) + */ + +struct LAP { + u_char dst; + u_char src; + u_char type; +}; +#define lapShortDDP 1 /* short DDP type */ +#define lapDDP 2 /* DDP type */ +#define lapKLAP 'K' /* Kinetics KLAP type */ + +/* Datagram Delivery Protocol */ + +struct atDDP { + u_short length; + u_short checksum; + u_short dstNet; + u_short srcNet; + u_char dstNode; + u_char srcNode; + u_char dstSkt; + u_char srcSkt; + u_char type; +}; + +struct atShortDDP { + u_short length; + u_char dstSkt; + u_char srcSkt; + u_char type; +}; + +#define ddpMaxWKS 0x7F +#define ddpMaxData 586 +#define ddpLengthMask 0x3FF +#define ddpHopShift 10 +#define ddpSize 13 /* size of DDP header (avoid struct padding) */ +#define ddpSSize 5 +#define ddpWKS 128 /* boundary of DDP well known sockets */ +#define ddpRTMP 1 /* RTMP type */ +#define ddpRTMPrequest 5 /* RTMP request type */ +#define ddpNBP 2 /* NBP type */ +#define ddpATP 3 /* ATP type */ +#define ddpECHO 4 /* ECHO type */ +#define ddpIP 22 /* IP type */ +#define ddpARP 23 /* ARP type */ +#define ddpKLAP 0x4b /* Kinetics KLAP type */ + + +/* AppleTalk Transaction Protocol */ + +struct atATP { + u_char control; + u_char bitmap; + u_short transID; + int32_t userData; +}; + +#define atpReqCode 0x40 +#define atpRspCode 0x80 +#define atpRelCode 0xC0 +#define atpXO 0x20 +#define atpEOM 0x10 +#define atpSTS 0x08 +#define atpFlagMask 0x3F +#define atpControlMask 0xF8 +#define atpMaxNum 8 +#define atpMaxData 578 + + +/* AppleTalk Echo Protocol */ + +struct atEcho { + u_char echoFunction; + u_char *echoData; +}; + +#define echoSkt 4 /* the echoer socket */ +#define echoSize 1 /* size of echo header */ +#define echoRequest 1 /* echo request */ +#define echoReply 2 /* echo request */ + + +/* Name Binding Protocol */ + +struct atNBP { + u_char control; + u_char id; +}; + +struct atNBPtuple { + u_short net; + u_char node; + u_char skt; + u_char enumerator; +}; + +#define nbpBrRq 0x10 +#define nbpLkUp 0x20 +#define nbpLkUpReply 0x30 + +#define nbpNIS 2 +#define nbpTupleMax 15 + +#define nbpHeaderSize 2 +#define nbpTupleSize 5 + +#define nbpSkt 2 /* NIS */ + + +/* Routing Table Maint. Protocol */ + +#define rtmpSkt 1 /* number of RTMP socket */ +#define rtmpSize 4 /* minimum size */ +#define rtmpTupleSize 3 + + +/* Zone Information Protocol */ + +struct zipHeader { + u_char command; + u_char netcount; +}; + +#define zipHeaderSize 2 +#define zipQuery 1 +#define zipReply 2 +#define zipTakedown 3 +#define zipBringup 4 +#define ddpZIP 6 +#define zipSkt 6 +#define GetMyZone 7 +#define GetZoneList 8 + +/* + * UDP port range used for ddp-in-udp encapsulation is 16512-16639 + * for client sockets (128-255) and 200-327 for server sockets + * (0-127). We also try to recognize the pre-April 88 server + * socket range of 768-895. + */ +#define atalk_port(p) \ + (((unsigned)((p) - 16512) < 128) || \ + ((unsigned)((p) - 200) < 128) || \ + ((unsigned)((p) - 768) < 128)) diff --git a/tcpdump.tproj/bootp.h b/tcpdump.tproj/bootp.h new file mode 100644 index 0000000..74dc2c2 --- /dev/null +++ b/tcpdump.tproj/bootp.h @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/bootp.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) */ +/* + * Bootstrap Protocol (BOOTP). RFC951 and RFC1048. + * + * This file specifies the "implementation-independent" BOOTP protocol + * information which is common to both client and server. + * + * Copyright 1988 by Carnegie Mellon. + * + * Permission to use, copy, modify, and distribute this program for any + * purpose and without fee is hereby granted, provided that this copyright + * and permission notice appear on all copies and supporting documentation, + * the name of Carnegie Mellon not be used in advertising or publicity + * pertaining to distribution of the program without specific prior + * permission, and notice be given in supporting documentation that copying + * and distribution is by permission of Carnegie Mellon and Stanford + * University. Carnegie Mellon makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + + +struct bootp { + unsigned char bp_op; /* packet opcode type */ + unsigned char bp_htype; /* hardware addr type */ + unsigned char bp_hlen; /* hardware addr length */ + unsigned char bp_hops; /* gateway hops */ + u_int32_t bp_xid; /* transaction ID */ + unsigned short bp_secs; /* seconds since boot began */ + unsigned short bp_unused; + struct in_addr bp_ciaddr; /* client IP address */ + struct in_addr bp_yiaddr; /* 'your' IP address */ + struct in_addr bp_siaddr; /* server IP address */ + struct in_addr bp_giaddr; /* gateway IP address */ + unsigned char bp_chaddr[16]; /* client hardware address */ + unsigned char bp_sname[64]; /* server host name */ + unsigned char bp_file[128]; /* boot file name */ + unsigned char bp_vend[64]; /* vendor-specific area */ +}; + +/* + * UDP port numbers, server and client. + */ +#define IPPORT_BOOTPS 67 +#define IPPORT_BOOTPC 68 + +#define BOOTREPLY 2 +#define BOOTREQUEST 1 + + +/* + * Vendor magic cookie (v_magic) for CMU + */ +#define VM_CMU "CMU" + +/* + * Vendor magic cookie (v_magic) for RFC1048 + */ +#define VM_RFC1048 { 99, 130, 83, 99 } + + + +/* + * RFC1048 tag values used to specify what information is being supplied in + * the vendor field of the packet. + */ + +#define TAG_PAD ((unsigned char) 0) +#define TAG_SUBNET_MASK ((unsigned char) 1) +#define TAG_TIME_OFFSET ((unsigned char) 2) +#define TAG_GATEWAY ((unsigned char) 3) +#define TAG_TIME_SERVER ((unsigned char) 4) +#define TAG_NAME_SERVER ((unsigned char) 5) +#define TAG_DOMAIN_SERVER ((unsigned char) 6) +#define TAG_LOG_SERVER ((unsigned char) 7) +#define TAG_COOKIE_SERVER ((unsigned char) 8) +#define TAG_LPR_SERVER ((unsigned char) 9) +#define TAG_IMPRESS_SERVER ((unsigned char) 10) +#define TAG_RLP_SERVER ((unsigned char) 11) +#define TAG_HOSTNAME ((unsigned char) 12) +#define TAG_BOOTSIZE ((unsigned char) 13) +#define TAG_END ((unsigned char) 255) +/* RFC1497 tags */ +#define TAG_DUMPPATH ((unsigned char) 14) +#define TAG_DOMAINNAME ((unsigned char) 15) +#define TAG_SWAP_SERVER ((unsigned char) 16) +#define TAG_ROOTPATH ((unsigned char) 17) +#define TAG_EXTPATH ((unsigned char) 18) + + + +/* + * "vendor" data permitted for CMU bootp clients. + */ + +struct cmu_vend { + unsigned char v_magic[4]; /* magic number */ + u_int32_t v_flags; /* flags/opcodes, etc. */ + struct in_addr v_smask; /* Subnet mask */ + struct in_addr v_dgate; /* Default gateway */ + struct in_addr v_dns1, v_dns2; /* Domain name servers */ + struct in_addr v_ins1, v_ins2; /* IEN-116 name servers */ + struct in_addr v_ts1, v_ts2; /* Time servers */ + unsigned char v_unused[24]; /* currently unused */ +}; + + +/* v_flags values */ +#define VF_SMASK 1 /* Subnet mask field contains valid data */ diff --git a/tcpdump.tproj/bpf_dump.c b/tcpdump.tproj/bpf_dump.c new file mode 100644 index 0000000..5c29e59 --- /dev/null +++ b/tcpdump.tproj/bpf_dump.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/bpf_dump.c,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include + +#include "interface.h" + +extern void bpf_dump(struct bpf_program *, int); + +void +bpf_dump(struct bpf_program *p, int option) +{ + struct bpf_insn *insn; + int i; + int n = p->bf_len; + + insn = p->bf_insns; + if (option > 2) { + printf("%d\n", n); + for (i = 0; i < n; ++insn, ++i) { + printf("%u %u %u %u\n", insn->code, + insn->jt, insn->jf, insn->k); + } + return ; + } + if (option > 1) { + for (i = 0; i < n; ++insn, ++i) + printf("{ 0x%x, %d, %d, 0x%08x },\n", + insn->code, insn->jt, insn->jf, insn->k); + return; + } + for (i = 0; i < n; ++insn, ++i) { +#ifdef BDEBUG + extern int bids[]; + printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); +#endif + puts(bpf_image(insn, i)); + } +} diff --git a/tcpdump.tproj/decnet.h b/tcpdump.tproj/decnet.h new file mode 100644 index 0000000..37a6127 --- /dev/null +++ b/tcpdump.tproj/decnet.h @@ -0,0 +1,476 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/decnet.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) + */ + +typedef unsigned char byte[1]; /* single byte field */ +typedef unsigned char word[2]; /* 2 byte field */ +typedef unsigned char longword[4]; /* 4 bytes field */ + +/* + * Definitions for DECNET Phase IV protocol headers + */ +union etheraddress { + unsigned char dne_addr[6]; /* full ethernet address */ + struct { + unsigned char dne_hiord[4]; /* DECnet HIORD prefix */ + unsigned char dne_nodeaddr[2]; /* DECnet node address */ + } dne_remote; +}; + +typedef union etheraddress etheraddr; /* Ethernet address */ + +#define HIORD 0x000400aa /* high 32-bits of address (swapped) */ + +#define AREAMASK 0176000 /* mask for area field */ +#define AREASHIFT 10 /* bit-offset for area field */ +#define NODEMASK 01777 /* mask for node address field */ + +#define DN_MAXADDL 20 /* max size of DECnet address */ +struct dn_naddr { + unsigned short a_len; /* length of address */ + unsigned char a_addr[DN_MAXADDL]; /* address as bytes */ +}; + +/* + * Define long and short header formats. + */ +struct shorthdr + { + byte sh_flags; /* route flags */ + word sh_dst; /* destination node address */ + word sh_src; /* source node address */ + byte sh_visits; /* visit count */ + }; + +struct longhdr + { + byte lg_flags; /* route flags */ + byte lg_darea; /* destination area (reserved) */ + byte lg_dsarea; /* destination subarea (reserved) */ + etheraddr lg_dst; /* destination id */ + byte lg_sarea; /* source area (reserved) */ + byte lg_ssarea; /* source subarea (reserved) */ + etheraddr lg_src; /* source id */ + byte lg_nextl2; /* next level 2 router (reserved) */ + byte lg_visits; /* visit count */ + byte lg_service; /* service class (reserved) */ + byte lg_pt; /* protocol type (reserved) */ + }; + +union routehdr + { + struct shorthdr rh_short; /* short route header */ + struct longhdr rh_long; /* long route header */ + }; + +/* + * Define the values of various fields in the protocol messages. + * + * 1. Data packet formats. + */ +#define RMF_MASK 7 /* mask for message type */ +#define RMF_SHORT 2 /* short message format */ +#define RMF_LONG 6 /* long message format */ +#ifndef RMF_RQR +#define RMF_RQR 010 /* request return to sender */ +#define RMF_RTS 020 /* returning to sender */ +#define RMF_IE 040 /* intra-ethernet packet */ +#endif /* RMR_RQR */ +#define RMF_FVER 0100 /* future version flag */ +#define RMF_PAD 0200 /* pad field */ +#define RMF_PADMASK 0177 /* pad field mask */ + +#define VIS_MASK 077 /* visit field mask */ + +/* + * 2. Control packet formats. + */ +#define RMF_CTLMASK 017 /* mask for message type */ +#define RMF_CTLMSG 01 /* control message indicator */ +#define RMF_INIT 01 /* initialization message */ +#define RMF_VER 03 /* verification message */ +#define RMF_TEST 05 /* hello and test message */ +#define RMF_L1ROUT 07 /* level 1 routing message */ +#define RMF_L2ROUT 011 /* level 2 routing message */ +#define RMF_RHELLO 013 /* router hello message */ +#define RMF_EHELLO 015 /* endnode hello message */ + +#define TI_L2ROUT 01 /* level 2 router */ +#define TI_L1ROUT 02 /* level 1 router */ +#define TI_ENDNODE 03 /* endnode */ +#define TI_VERIF 04 /* verification required */ +#define TI_BLOCK 010 /* blocking requested */ + +#define VE_VERS 2 /* version number (2) */ +#define VE_ECO 0 /* ECO number */ +#define VE_UECO 0 /* user ECO number (0) */ + +#define P3_VERS 1 /* phase III version number (1) */ +#define P3_ECO 3 /* ECO number (3) */ +#define P3_UECO 0 /* user ECO number (0) */ + +#define II_L2ROUT 01 /* level 2 router */ +#define II_L1ROUT 02 /* level 1 router */ +#define II_ENDNODE 03 /* endnode */ +#define II_VERIF 04 /* verification required */ +#define II_NOMCAST 040 /* no multicast traffic accepted */ +#define II_BLOCK 0100 /* blocking requested */ +#define II_TYPEMASK 03 /* mask for node type */ + +#define TESTDATA 0252 /* test data bytes */ +#define TESTLEN 1 /* length of transmitted test data */ + +/* + * Define control message formats. + */ +struct initmsgIII /* phase III initialization message */ + { + byte inIII_flags; /* route flags */ + word inIII_src; /* source node address */ + byte inIII_info; /* routing layer information */ + word inIII_blksize; /* maximum data link block size */ + byte inIII_vers; /* version number */ + byte inIII_eco; /* ECO number */ + byte inIII_ueco; /* user ECO number */ + byte inIII_rsvd; /* reserved image field */ + }; + +struct initmsg /* initialization message */ + { + byte in_flags; /* route flags */ + word in_src; /* source node address */ + byte in_info; /* routing layer information */ + word in_blksize; /* maximum data link block size */ + byte in_vers; /* version number */ + byte in_eco; /* ECO number */ + byte in_ueco; /* user ECO number */ + word in_hello; /* hello timer */ + byte in_rsvd; /* reserved image field */ + }; + +struct verifmsg /* verification message */ + { + byte ve_flags; /* route flags */ + word ve_src; /* source node address */ + byte ve_fcnval; /* function value image field */ + }; + +struct testmsg /* hello and test message */ + { + byte te_flags; /* route flags */ + word te_src; /* source node address */ + byte te_data; /* test data image field */ + }; + +struct l1rout /* level 1 routing message */ + { + byte r1_flags; /* route flags */ + word r1_src; /* source node address */ + byte r1_rsvd; /* reserved field */ + }; + +struct l2rout /* level 2 routing message */ + { + byte r2_flags; /* route flags */ + word r2_src; /* source node address */ + byte r2_rsvd; /* reserved field */ + }; + +struct rhellomsg /* router hello message */ + { + byte rh_flags; /* route flags */ + byte rh_vers; /* version number */ + byte rh_eco; /* ECO number */ + byte rh_ueco; /* user ECO number */ + etheraddr rh_src; /* source id */ + byte rh_info; /* routing layer information */ + word rh_blksize; /* maximum data link block size */ + byte rh_priority; /* router's priority */ + byte rh_area; /* reserved */ + word rh_hello; /* hello timer */ + byte rh_mpd; /* reserved */ + }; + +struct ehellomsg /* endnode hello message */ + { + byte eh_flags; /* route flags */ + byte eh_vers; /* version number */ + byte eh_eco; /* ECO number */ + byte eh_ueco; /* user ECO number */ + etheraddr eh_src; /* source id */ + byte eh_info; /* routing layer information */ + word eh_blksize; /* maximum data link block size */ + byte eh_area; /* area (reserved) */ + byte eh_seed[8]; /* verification seed */ + etheraddr eh_router; /* designated router */ + word eh_hello; /* hello timer */ + byte eh_mpd; /* (reserved) */ + byte eh_data; /* test data image field */ + }; + +union controlmsg + { + struct initmsg cm_init; /* initialization message */ + struct verifmsg cm_ver; /* verification message */ + struct testmsg cm_test; /* hello and test message */ + struct l1rout cm_l1rou; /* level 1 routing message */ + struct l2rout cm_l2rout; /* level 2 routing message */ + struct rhellomsg cm_rhello; /* router hello message */ + struct ehellomsg cm_ehello; /* endnode hello message */ + }; + +/* Macros for decoding routing-info fields */ +#define RI_COST(x) ((x)&0777) +#define RI_HOPS(x) (((x)>>10)&037) + +/* + * NSP protocol fields and values. + */ + +#define NSP_TYPEMASK 014 /* mask to isolate type code */ +#define NSP_SUBMASK 0160 /* mask to isolate subtype code */ +#define NSP_SUBSHFT 4 /* shift to move subtype code */ + +#define MFT_DATA 0 /* data message */ +#define MFT_ACK 04 /* acknowledgement message */ +#define MFT_CTL 010 /* control message */ + +#define MFS_ILS 020 /* data or I/LS indicator */ +#define MFS_BOM 040 /* beginning of message (data) */ +#define MFS_MOM 0 /* middle of message (data) */ +#define MFS_EOM 0100 /* end of message (data) */ +#define MFS_INT 040 /* interrupt message */ + +#define MFS_DACK 0 /* data acknowledgement */ +#define MFS_IACK 020 /* I/LS acknowledgement */ +#define MFS_CACK 040 /* connect acknowledgement */ + +#define MFS_NOP 0 /* no operation */ +#define MFS_CI 020 /* connect initiate */ +#define MFS_CC 040 /* connect confirm */ +#define MFS_DI 060 /* disconnect initiate */ +#define MFS_DC 0100 /* disconnect confirm */ +#define MFS_RCI 0140 /* retransmitted connect initiate */ + +#define SGQ_ACK 0100000 /* ack */ +#define SGQ_NAK 0110000 /* negative ack */ +#define SGQ_OACK 0120000 /* other channel ack */ +#define SGQ_ONAK 0130000 /* other channel negative ack */ +#define SGQ_MASK 07777 /* mask to isolate seq # */ +#define SGQ_OTHER 020000 /* other channel qualifier */ +#define SGQ_DELAY 010000 /* ack delay flag */ + +#define SGQ_EOM 0100000 /* pseudo flag for end-of-message */ + +#define LSM_MASK 03 /* mask for modifier field */ +#define LSM_NOCHANGE 0 /* no change */ +#define LSM_DONOTSEND 1 /* do not send data */ +#define LSM_SEND 2 /* send data */ + +#define LSI_MASK 014 /* mask for interpretation field */ +#define LSI_DATA 0 /* data segment or message count */ +#define LSI_INTR 4 /* interrupt request count */ +#define LSI_INTM 0377 /* funny marker for int. message */ + +#define COS_MASK 014 /* mask for flow control field */ +#define COS_NONE 0 /* no flow control */ +#define COS_SEGMENT 04 /* segment flow control */ +#define COS_MESSAGE 010 /* message flow control */ +#define COS_CRYPTSER 020 /* cryptographic services requested */ +#define COS_DEFAULT 1 /* default value for field */ + +#define COI_MASK 3 /* mask for version field */ +#define COI_32 0 /* version 3.2 */ +#define COI_31 1 /* version 3.1 */ +#define COI_40 2 /* version 4.0 */ +#define COI_41 3 /* version 4.1 */ + +#define MNU_MASK 140 /* mask for session control version */ +#define MNU_10 000 /* session V1.0 */ +#define MNU_20 040 /* session V2.0 */ +#define MNU_ACCESS 1 /* access control present */ +#define MNU_USRDATA 2 /* user data field present */ +#define MNU_INVKPROXY 4 /* invoke proxy field present */ +#define MNU_UICPROXY 8 /* use uic-based proxy */ + +#define DC_NORESOURCES 1 /* no resource reason code */ +#define DC_NOLINK 41 /* no link terminate reason code */ +#define DC_COMPLETE 42 /* disconnect complete reason code */ + +#define DI_NOERROR 0 /* user disconnect */ +#define DI_SHUT 3 /* node is shutting down */ +#define DI_NOUSER 4 /* destination end user does not exist */ +#define DI_INVDEST 5 /* invalid end user destination */ +#define DI_REMRESRC 6 /* insufficient remote resources */ +#define DI_TPA 8 /* third party abort */ +#define DI_PROTOCOL 7 /* protocol error discovered */ +#define DI_ABORT 9 /* user abort */ +#define DI_LOCALRESRC 32 /* insufficient local resources */ +#define DI_REMUSERRESRC 33 /* insufficient remote user resources */ +#define DI_BADACCESS 34 /* bad access control information */ +#define DI_BADACCNT 36 /* bad ACCOUNT information */ +#define DI_CONNECTABORT 38 /* connect request cancelled */ +#define DI_TIMEDOUT 38 /* remote node or user crashed */ +#define DI_UNREACHABLE 39 /* local timers expired due to ... */ +#define DI_BADIMAGE 43 /* bad image data in connect */ +#define DI_SERVMISMATCH 54 /* cryptographic service mismatch */ + +#define UC_OBJREJECT 0 /* object rejected connect */ +#define UC_USERDISCONNECT 0 /* user disconnect */ +#define UC_RESOURCES 1 /* insufficient resources (local or remote) */ +#define UC_NOSUCHNODE 2 /* unrecognized node name */ +#define UC_REMOTESHUT 3 /* remote node shutting down */ +#define UC_NOSUCHOBJ 4 /* unrecognized object */ +#define UC_INVOBJFORMAT 5 /* invalid object name format */ +#define UC_OBJTOOBUSY 6 /* object too busy */ +#define UC_NETWORKABORT 8 /* network abort */ +#define UC_USERABORT 9 /* user abort */ +#define UC_INVNODEFORMAT 10 /* invalid node name format */ +#define UC_LOCALSHUT 11 /* local node shutting down */ +#define UC_ACCESSREJECT 34 /* invalid access control information */ +#define UC_NORESPONSE 38 /* no response from object */ +#define UC_UNREACHABLE 39 /* node unreachable */ + +/* + * NSP message formats. + */ +struct nsphdr /* general nsp header */ + { + byte nh_flags; /* message flags */ + word nh_dst; /* destination link address */ + word nh_src; /* source link address */ + }; + +struct seghdr /* data segment header */ + { + byte sh_flags; /* message flags */ + word sh_dst; /* destination link address */ + word sh_src; /* source link address */ + word sh_seq[3]; /* sequence numbers */ + }; + +struct minseghdr /* minimum data segment header */ + { + byte ms_flags; /* message flags */ + word ms_dst; /* destination link address */ + word ms_src; /* source link address */ + word ms_seq; /* sequence number */ + }; + +struct lsmsg /* link service message (after hdr) */ + { + byte ls_lsflags; /* link service flags */ + byte ls_fcval; /* flow control value */ + }; + +struct ackmsg /* acknowledgement message */ + { + byte ak_flags; /* message flags */ + word ak_dst; /* destination link address */ + word ak_src; /* source link address */ + word ak_acknum[2]; /* acknowledgement numbers */ + }; + +struct minackmsg /* minimum acknowledgement message */ + { + byte mk_flags; /* message flags */ + word mk_dst; /* destination link address */ + word mk_src; /* source link address */ + word mk_acknum; /* acknowledgement number */ + }; + +struct ciackmsg /* connect acknowledgement message */ + { + byte ck_flags; /* message flags */ + word ck_dst; /* destination link address */ + }; + +struct cimsg /* connect initiate message */ + { + byte ci_flags; /* message flags */ + word ci_dst; /* destination link address (0) */ + word ci_src; /* source link address */ + byte ci_services; /* requested services */ + byte ci_info; /* information */ + word ci_segsize; /* maximum segment size */ + }; + +struct ccmsg /* connect confirm message */ + { + byte cc_flags; /* message flags */ + word cc_dst; /* destination link address */ + word cc_src; /* source link address */ + byte cc_services; /* requested services */ + byte cc_info; /* information */ + word cc_segsize; /* maximum segment size */ + byte cc_optlen; /* optional data length */ + }; + +struct cnmsg /* generic connect message */ + { + byte cn_flags; /* message flags */ + word cn_dst; /* destination link address */ + word cn_src; /* source link address */ + byte cn_services; /* requested services */ + byte cn_info; /* information */ + word cn_segsize; /* maximum segment size */ + }; + +struct dimsg /* disconnect initiate message */ + { + byte di_flags; /* message flags */ + word di_dst; /* destination link address */ + word di_src; /* source link address */ + word di_reason; /* reason code */ + byte di_optlen; /* optional data length */ + }; + +struct dcmsg /* disconnect confirm message */ + { + byte dc_flags; /* message flags */ + word dc_dst; /* destination link address */ + word dc_src; /* source link address */ + word dc_reason; /* reason code */ + }; diff --git a/tcpdump.tproj/ethertype.h b/tcpdump.tproj/ethertype.h new file mode 100644 index 0000000..43726ac --- /dev/null +++ b/tcpdump.tproj/ethertype.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993, 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/ethertype.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) + */ + +/* Types missing from some systems */ + +#ifndef ETHERTYPE_NS +#define ETHERTYPE_NS 0x0600 +#endif +#ifndef ETHERTYPE_SPRITE +#define ETHERTYPE_SPRITE 0x0500 +#endif +#ifndef ETHERTYPE_TRAIL +#define ETHERTYPE_TRAIL 0x1000 +#endif +#ifndef ETHERTYPE_MOPDL +#define ETHERTYPE_MOPDL 0x6001 +#endif +#ifndef ETHERTYPE_MOPRC +#define ETHERTYPE_MOPRC 0x6002 +#endif +#ifndef ETHERTYPE_DN +#define ETHERTYPE_DN 0x6003 +#endif +#ifndef ETHERTYPE_LAT +#define ETHERTYPE_LAT 0x6004 +#endif +#ifndef ETHERTYPE_SCA +#define ETHERTYPE_SCA 0x6007 +#endif +#ifndef ETHERTYPE_REVARP +#define ETHERTYPE_REVARP 0x8035 +#endif +#ifndef ETHERTYPE_LANBRIDGE +#define ETHERTYPE_LANBRIDGE 0x8038 +#endif +#ifndef ETHERTYPE_DECDNS +#define ETHERTYPE_DECDNS 0x803c +#endif +#ifndef ETHERTYPE_DECDTS +#define ETHERTYPE_DECDTS 0x803e +#endif +#ifndef ETHERTYPE_VEXP +#define ETHERTYPE_VEXP 0x805b +#endif +#ifndef ETHERTYPE_VPROD +#define ETHERTYPE_VPROD 0x805c +#endif +#ifndef ETHERTYPE_ATALK +#define ETHERTYPE_ATALK 0x809b +#endif +#ifndef ETHERTYPE_AARP +#define ETHERTYPE_AARP 0x80f3 +#endif +#ifndef ETHERTYPE_LOOPBACK +#define ETHERTYPE_LOOPBACK 0x9000 +#endif diff --git a/tcpdump.tproj/extract.h b/tcpdump.tproj/extract.h new file mode 100644 index 0000000..f3213d4 --- /dev/null +++ b/tcpdump.tproj/extract.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/extract.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) + */ + +/* Network to host order macros */ + +#ifdef LBL_ALIGN +#define EXTRACT_16BITS(p) \ + ((u_short)*((u_char *)(p) + 0) << 8 | \ + (u_short)*((u_char *)(p) + 1)) +#define EXTRACT_32BITS(p) \ + ((u_int32_t)*((u_char *)(p) + 0) << 24 | \ + (u_int32_t)*((u_char *)(p) + 1) << 16 | \ + (u_int32_t)*((u_char *)(p) + 2) << 8 | \ + (u_int32_t)*((u_char *)(p) + 3)) +#else +#define EXTRACT_16BITS(p) \ + ((u_short)ntohs(*(u_short *)(p))) +#define EXTRACT_32BITS(p) \ + ((u_int32_t)ntohl(*(u_int32_t *)(p))) +#endif + +#define EXTRACT_24BITS(p) \ + ((u_int32_t)*((u_char *)(p) + 0) << 16 | \ + (u_int32_t)*((u_char *)(p) + 1) << 8 | \ + (u_int32_t)*((u_char *)(p) + 2)) + +/* Little endian protocol host order macros */ + +#define EXTRACT_LE_8BITS(p) (*(p)) +#define EXTRACT_LE_16BITS(p) \ + ((u_short)*((u_char *)(p) + 1) << 8 | \ + (u_short)*((u_char *)(p) + 0)) +#define EXTRACT_LE_32BITS(p) \ + ((u_int32_t)*((u_char *)(p) + 3) << 24 | \ + (u_int32_t)*((u_char *)(p) + 2) << 16 | \ + (u_int32_t)*((u_char *)(p) + 1) << 8 | \ + (u_int32_t)*((u_char *)(p) + 0)) diff --git a/tcpdump.tproj/fddi.h b/tcpdump.tproj/fddi.h new file mode 100644 index 0000000..21920f4 --- /dev/null +++ b/tcpdump.tproj/fddi.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/fddi.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) + */ + +/* + * Based on Ultrix if_fddi.h + */ + +/* + * This stuff should come from a system header file, but there's no + * obviously portable way to do that and it's not really going + * to change from system to system (except for the padding business). + */ + +struct fddi_header { + u_char fddi_fc; /* frame control */ + u_char fddi_dhost[6]; + u_char fddi_shost[6]; +}; + + +/* Useful values for fddi_fc (frame control) field */ + +/* + * FDDI Frame Control bits + */ +#define FDDIFC_C 0x80 /* Class bit */ +#define FDDIFC_L 0x40 /* Address length bit */ +#define FDDIFC_F 0x30 /* Frame format bits */ +#define FDDIFC_Z 0x0f /* Control bits */ + +/* + * FDDI Frame Control values. (48-bit addressing only). + */ +#define FDDIFC_VOID 0x40 /* Void frame */ +#define FDDIFC_NRT 0x80 /* Nonrestricted token */ +#define FDDIFC_RT 0xc0 /* Restricted token */ +#define FDDIFC_SMT_INFO 0x41 /* SMT Info */ +#define FDDIFC_SMT_NSA 0x4F /* SMT Next station adrs */ +#define FDDIFC_MAC_BEACON 0xc2 /* MAC Beacon frame */ +#define FDDIFC_MAC_CLAIM 0xc3 /* MAC Claim frame */ +#define FDDIFC_LLC_ASYNC 0x50 /* Async. LLC frame */ +#define FDDIFC_LLC_SYNC 0xd0 /* Sync. LLC frame */ +#define FDDIFC_IMP_ASYNC 0x60 /* Implementor Async. */ +#define FDDIFC_IMP_SYNC 0xe0 /* Implementor Synch. */ +#define FDDIFC_SMT 0x40 /* SMT frame */ +#define FDDIFC_MAC 0xc0 /* MAC frame */ + +#define FDDIFC_CLFF 0xF0 /* Class/Length/Format bits */ +#define FDDIFC_ZZZZ 0x0F /* Control bits */ diff --git a/tcpdump.tproj/gnuc.h b/tcpdump.tproj/gnuc.h new file mode 100644 index 0000000..a88d32c --- /dev/null +++ b/tcpdump.tproj/gnuc.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/gnuc.h,v 1.1.1.1 1999/05/02 03:58:31 wsanchez Exp $ (LBL) */ + +/* Define __P() macro, if necessary */ +#ifndef __P +#if __STDC__ +#define __P(protos) protos +#else +#define __P(protos) () +#endif +#endif + +/* inline foo */ +#ifdef __GNUC__ +#define inline __inline +#else +#define inline +#endif + +/* + * Handle new and old "dead" routine prototypes + * + * For example: + * + * __dead void foo(void) __attribute__((volatile)); + * + */ +#ifdef __GNUC__ +#ifndef __dead +#define __dead volatile +#endif +#if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#ifndef __attribute__ +#define __attribute__(args) +#endif +#endif +#else +#ifndef __dead +#define __dead +#endif +#ifndef __attribute__ +#define __attribute__(args) +#endif +#endif diff --git a/tcpdump.tproj/igrp.h b/tcpdump.tproj/igrp.h new file mode 100644 index 0000000..ec55bdf --- /dev/null +++ b/tcpdump.tproj/igrp.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* Cisco IGRP definitions */ + +/* IGRP Header */ + +struct igrphdr { +#ifdef WORDS_BIGENDIAN + u_char ig_v:4; /* protocol version number */ + u_char ig_op:4; /* opcode */ +#else + u_char ig_op:4; /* opcode */ + u_char ig_v:4; /* protocol version number */ +#endif + u_char ig_ed; /* edition number */ + u_short ig_as; /* autonomous system number */ + u_short ig_ni; /* number of subnet in local net */ + u_short ig_ns; /* number of networks in AS */ + u_short ig_nx; /* number of networks ouside AS */ + u_short ig_sum; /* checksum of IGRP header & data */ +}; + +#define IGRP_UPDATE 1 +#define IGRP_REQUEST 2 + +/* IGRP routing entry */ + +struct igrprte { + u_char igr_net[3]; /* 3 significant octets of IP address */ + u_char igr_dly[3]; /* delay in tens of microseconds */ + u_char igr_bw[3]; /* bandwidth in units of 1 kb/s */ + u_char igr_mtu[2]; /* MTU in octets */ + u_char igr_rel; /* percent packets successfully tx/rx */ + u_char igr_ld; /* percent of channel occupied */ + u_char igr_hct; /* hop count */ +}; + +#define IGRP_RTE_SIZE 14 /* don't believe sizeof ! */ diff --git a/tcpdump.tproj/interface.h b/tcpdump.tproj/interface.h new file mode 100644 index 0000000..089c4dd --- /dev/null +++ b/tcpdump.tproj/interface.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/interface.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL) + */ + +#ifndef tcpdump_interface_h +#define tcpdump_interface_h +#ifndef IPPROTO_ND +#define IPPROTO_ND 77 +#endif + + +#include "gnuc.h" +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +struct tok { + int v; /* value */ + char *s; /* string */ +}; + +extern int dflag; /* print filter code */ +extern int eflag; /* print ethernet header */ +extern int nflag; /* leave addresses as numbers */ +extern int Nflag; /* remove domains from printed host names */ +extern int qflag; /* quick (shorter) output */ +extern int Sflag; /* print raw TCP sequence numbers */ +extern int tflag; /* print packet arrival time */ +extern int vflag; /* verbose */ +extern int xflag; /* print packet in hex */ + +extern int packettype; /* as specified by -T */ +#define PT_VAT 1 /* Visual Audio Tool */ +#define PT_WB 2 /* distributed White Board */ +#define PT_RPC 3 /* Remote Procedure Call */ +#define PT_RTP 4 /* Real-Time Applications protocol */ +#define PT_RTCP 5 /* Real-Time Applications control protocol */ + +#ifndef min +#define min(a,b) ((a)>(b)?(b):(a)) +#endif +#ifndef max +#define max(a,b) ((b)>(a)?(b):(a)) +#endif + +/* + * The default snapshot length. This value allows most printers to print + * useful information while keeping the amount of unwanted data down. + * In particular, it allows for an ethernet header, tcp/ip header, and + * 14 bytes of data (assuming no ip options). + */ +#define DEFAULT_SNAPLEN 68 + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 4321 +#define LITTLE_ENDIAN 1234 +#endif + +#ifdef ETHER_HEADER_HAS_EA +#define ESRC(ep) ((ep)->ether_shost.ether_addr_octet) +#define EDST(ep) ((ep)->ether_dhost.ether_addr_octet) +#else +#define ESRC(ep) ((ep)->ether_shost) +#define EDST(ep) ((ep)->ether_dhost) +#endif + +#ifdef ETHER_ARP_HAS_X +#define SHA(ap) ((ap)->arp_xsha) +#define THA(ap) ((ap)->arp_xtha) +#define SPA(ap) ((ap)->arp_xspa) +#define TPA(ap) ((ap)->arp_xtpa) +#else +#ifdef ETHER_ARP_HAS_EA +#define SHA(ap) ((ap)->arp_sha.ether_addr_octet) +#define THA(ap) ((ap)->arp_tha.ether_addr_octet) +#else +#define SHA(ap) ((ap)->arp_sha) +#define THA(ap) ((ap)->arp_tha) +#endif +#define SPA(ap) ((ap)->arp_spa) +#define TPA(ap) ((ap)->arp_tpa) +#endif + +#ifndef NTOHL +#define NTOHL(x) (x) = ntohl(x) +#define NTOHS(x) (x) = ntohs(x) +#define HTONL(x) (x) = htonl(x) +#define HTONS(x) (x) = htons(x) +#endif +#endif + +extern char *program_name; /* used to generate self-identifying messages */ + +extern int32_t thiszone; /* seconds offset from gmt to local time */ + +extern int snaplen; +/* global pointers to beginning and end of current packet (during printing) */ +extern const u_char *packetp; +extern const u_char *snapend; + +/* True if "l" bytes of "var" were captured */ +#define TTEST2(var, l) ((u_char *)&(var) <= snapend - (l)) + +/* True if "var" was captured */ +#define TTEST(var) TTEST2(var, sizeof(var)) + +/* Bail if "l" bytes of "var" were not captured */ +#define TCHECK2(var, l) if (!TTEST2(var, l)) goto trunc + +/* Bail if "var" was not captured */ +#define TCHECK(var) TCHECK2(var, sizeof(var)) + +#ifdef __STDC__ +struct timeval; +#endif + +extern void ts_print(const struct timeval *); +extern int32_t gmt2local(void); + +extern int fn_print(const u_char *, const u_char *); +extern int fn_printn(const u_char *, u_int, const u_char *); +extern const char *tok2str(const struct tok *, const char *, int); +extern char *dnaddr_string(u_short); +extern char *savestr(const char *); + +extern void wrapup(int); + +#if __STDC__ +extern __dead void error(const char *, ...) + __attribute__((volatile, format (printf, 1, 2))); +extern void warning(const char *, ...) __attribute__ ((format (printf, 1, 2))); +#endif + +extern char *read_infile(char *); +extern char *copy_argv(char **); + +extern char *isonsap_string(const u_char *); +extern char *llcsap_string(u_char); +extern char *protoid_string(const u_char *); +extern char *dnname_string(u_short); +extern char *dnnum_string(u_short); + +/* The printer routines. */ + +#ifdef __STDC__ +struct pcap_pkthdr; +#endif + +extern int ether_encap_print(u_short, const u_char *, u_int, u_int); +extern int llc_print(const u_char *, u_int, u_int, const u_char *, + const u_char *); +extern void aarp_print(const u_char *, u_int); +extern void arp_print(const u_char *, u_int, u_int); +extern void atalk_print(const u_char *, u_int); +extern void atm_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); +extern void bootp_print(const u_char *, u_int, u_short, u_short); +extern void decnet_print(const u_char *, u_int, u_int); +extern void default_print(const u_char *, u_int); +extern void default_print_unaligned(const u_char *, u_int); +extern void dvmrp_print(const u_char *, u_int); +extern void egp_print(const u_char *, u_int, const u_char *); +extern void ether_if_print(u_char *, const struct pcap_pkthdr *, + const u_char *); +extern void fddi_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); +extern void gre_print(const u_char *, u_int); +extern void icmp_print(const u_char *, const u_char *); +extern void igrp_print(const u_char *, u_int, const u_char *); +extern void ip_print(const u_char *, u_int); +extern void ipx_print(const u_char *, u_int); +extern void isoclns_print(const u_char *, u_int, u_int, const u_char *, + const u_char *); +extern void krb_print(const u_char *, u_int); +extern void nfsreply_print(const u_char *, u_int, const u_char *); +extern void nfsreq_print(const u_char *, u_int, const u_char *); +extern void ns_print(const u_char *, u_int); +extern void ntp_print(const u_char *, u_int); +extern void null_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); +extern void ospf_print(const u_char *, u_int, const u_char *); +extern void pim_print(const u_char *, u_int); +extern void ppp_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); +extern void rip_print(const u_char *, u_int); +extern void sl_if_print(u_char *, const struct pcap_pkthdr *, const u_char *); +extern void snmp_print(const u_char *, u_int); +extern void sunrpcrequest_print(const u_char *, u_int, const u_char *); +extern void tcp_print(const u_char *, u_int, const u_char *); +extern void tftp_print(const u_char *, u_int); +extern void udp_print(const u_char *, u_int, const u_char *); +extern void wb_print(const void *, u_int); diff --git a/tcpdump.tproj/ipx.h b/tcpdump.tproj/ipx.h new file mode 100644 index 0000000..e1dda81 --- /dev/null +++ b/tcpdump.tproj/ipx.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * IPX protocol formats + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/ipx.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ + */ + +/* well-known sockets */ +#define IPX_SKT_NCP 0x0451 +#define IPX_SKT_SAP 0x0452 +#define IPX_SKT_RIP 0x0453 +#define IPX_SKT_NETBIOS 0x0455 +#define IPX_SKT_DIAGNOSTICS 0x0456 + +/* IPX transport header */ +struct ipxHdr { + u_short cksum; /* Checksum */ + u_short length; /* Length, in bytes, including header */ + u_char tCtl; /* Transport Control (i.e. hop count) */ + u_char pType; /* Packet Type (i.e. level 2 protocol) */ + u_short dstNet[2]; /* destination net */ + u_char dstNode[6]; /* destination node */ + u_short dstSkt; /* destination socket */ + u_short srcNet[2]; /* source net */ + u_char srcNode[6]; /* source node */ + u_short srcSkt; /* source socket */ +} ipx_hdr_t; + +#define ipxSize 30 + diff --git a/tcpdump.tproj/llc.h b/tcpdump.tproj/llc.h new file mode 100644 index 0000000..4432514 --- /dev/null +++ b/tcpdump.tproj/llc.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/llc.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL) + */ + +/* + * This stuff should come from a system header file, but there's no + * obviously portable way to do that and it's not really going + * to change from system to system. + */ + +/* + * A somewhat abstracted view of the LLC header + */ + +struct llc { + u_char dsap; + u_char ssap; + union { + u_char u_ctl; + u_short is_ctl; + struct { + u_char snap_ui; + u_char snap_pi[5]; + } snap; + struct { + u_char snap_ui; + u_char snap_orgcode[3]; + u_char snap_ethertype[2]; + } snap_ether; + } ctl; +}; + +#define llcui ctl.snap.snap_ui +#define llcpi ctl.snap.snap_pi +#define orgcode ctl.snap_ether.snap_orgcode +#define ethertype ctl.snap_ether.snap_ethertype +#define llcis ctl.is_ctl +#define llcu ctl.u_ctl + +#define LLC_U_FMT 3 +#define LLC_GSAP 1 +#define LLC_S_FMT 1 + +#define LLC_U_POLL 0x10 +#define LLC_IS_POLL 0x0001 +#define LLC_XID_FI 0x81 + +#define LLC_U_CMD(u) ((u) & 0xef) +#define LLC_UI 0x03 +#define LLC_UA 0x63 +#define LLC_DISC 0x43 +#define LLC_DM 0x0f +#define LLC_SABME 0x6f +#define LLC_TEST 0xe3 +#define LLC_XID 0xaf +#define LLC_FRMR 0x87 + +#define LLC_S_CMD(is) (((is) >> 10) & 0x03) +#define LLC_RR 0x0100 +#define LLC_RNR 0x0500 +#define LLC_REJ 0x0900 + +#define LLC_IS_NR(is) (((is) >> 9) & 0x7f) +#define LLC_I_NS(is) (((is) >> 1) & 0x7f) + +#ifndef LLCSAP_NULL +#define LLCSAP_NULL 0x00 +#endif +#ifndef LLCSAP_GLOBAL +#define LLCSAP_GLOBAL 0xff +#endif +#ifndef LLCSAP_8021B +#define LLCSAP_8021B_I 0x02 +#endif +#ifndef LLCSAP_8021B +#define LLCSAP_8021B_G 0x03 +#endif +#ifndef LLCSAP_IP +#define LLCSAP_IP 0x06 +#endif +#ifndef LLCSAP_PROWAYNM +#define LLCSAP_PROWAYNM 0x0e +#endif +#ifndef LLCSAP_8021D +#define LLCSAP_8021D 0x42 +#endif +#ifndef LLCSAP_RS511 +#define LLCSAP_RS511 0x4e +#endif +#ifndef LLCSAP_ISO8208 +#define LLCSAP_ISO8208 0x7e +#endif +#ifndef LLCSAP_PROWAY +#define LLCSAP_PROWAY 0x8e +#endif +#ifndef LLCSAP_SNAP +#define LLCSAP_SNAP 0xaa +#endif +#ifndef LLCSAP_ISONS +#define LLCSAP_ISONS 0xfe +#endif diff --git a/tcpdump.tproj/machdep.c b/tcpdump.tproj/machdep.c new file mode 100644 index 0000000..df136f4 --- /dev/null +++ b/tcpdump.tproj/machdep.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/machdep.c,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)"; +#endif + +#include +#ifdef __osf__ +#include +#include +#endif + +#include + +#include "machdep.h" + +int +abort_on_misalignment(char *ebuf) +{ +#ifdef __osf__ + static int buf[2] = { SSIN_UACPROC, UAC_SIGBUS }; + + if (setsysinfo(SSI_NVPAIRS, (caddr_t)buf, 1, 0, 0) < 0) { + (void)sprintf(ebuf, "setsysinfo: %s", pcap_strerror(errno)); + return (-1); + } +#endif + return (0); +} diff --git a/tcpdump.tproj/machdep.h b/tcpdump.tproj/machdep.h new file mode 100644 index 0000000..7e8d45a --- /dev/null +++ b/tcpdump.tproj/machdep.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/machdep.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL) + */ +#ifndef tcpdump_machdep_h +#define tcpdump_machdep_h + +int abort_on_misalignment(char *); +#endif diff --git a/tcpdump.tproj/mib.h b/tcpdump.tproj/mib.h new file mode 100644 index 0000000..454d6b2 --- /dev/null +++ b/tcpdump.tproj/mib.h @@ -0,0 +1,1279 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * This file was generated by tcpdump/makemib on Wed Sep 26 12:12:31 EDT 1990 + * You probably don't want to edit this by hand! + * + * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer +}; + */ + +/* parse problem: new name "mib" for mgmt.mib(1) ignored */ +/* parse problem: no parent for 0.nullSpecific(0) */ +struct obj +_proteon_obj = { + "proteon", 1, 0, + NULL, NULL +}, +_ibm_obj = { + "ibm", 2, 0, + NULL, &_proteon_obj +}, +_cmu_obj = { + "cmu", 3, 0, + NULL, &_ibm_obj +}, +_unix_obj = { + "unix", 4, 0, + NULL, &_cmu_obj +}, +_acc_obj = { + "acc", 5, 0, + NULL, &_unix_obj +}, +_twg_obj = { + "twg", 6, 0, + NULL, &_acc_obj +}, +_cayman_obj = { + "cayman", 7, 0, + NULL, &_twg_obj +}, +_nysernet_obj = { + "nysernet", 8, 0, + NULL, &_cayman_obj +}, +_cisco_obj = { + "cisco", 9, 0, + NULL, &_nysernet_obj +}, +_nsc_obj = { + "nsc", 10, 0, + NULL, &_cisco_obj +}, +_hp_obj = { + "hp", 11, 0, + NULL, &_nsc_obj +}, +_epilogue_obj = { + "epilogue", 12, 0, + NULL, &_hp_obj +}, +_utennessee_obj = { + "utennessee", 13, 0, + NULL, &_epilogue_obj +}, +_bbn_obj = { + "bbn", 14, 0, + NULL, &_utennessee_obj +}, +_xylogics_obj = { + "xylogics", 15, 0, + NULL, &_bbn_obj +}, +_unisys_obj = { + "unisys", 16, 0, + NULL, &_xylogics_obj +}, +_canstar_obj = { + "canstar", 17, 0, + NULL, &_unisys_obj +}, +_wellfleet_obj = { + "wellfleet", 18, 0, + NULL, &_canstar_obj +}, +_trw_obj = { + "trw", 19, 0, + NULL, &_wellfleet_obj +}, +_mit_obj = { + "mit", 20, 0, + NULL, &_trw_obj +}, +_eon_obj = { + "eon", 21, 0, + NULL, &_mit_obj +}, +_spartacus_obj = { + "spartacus", 22, 0, + NULL, &_eon_obj +}, +_excelan_obj = { + "excelan", 23, 0, + NULL, &_spartacus_obj +}, +_spider_obj = { + "spider", 24, 0, + NULL, &_excelan_obj +}, +_nsfnet_obj = { + "nsfnet", 25, 0, + NULL, &_spider_obj +}, +_sytek_obj = { + "sytek", 26, 0, + NULL, &_nsfnet_obj +}, +_intergraph_obj = { + "intergraph", 27, 0, + NULL, &_sytek_obj +}, +_interlan_obj = { + "interlan", 28, 0, + NULL, &_intergraph_obj +}, +_vitalink_obj = { + "vitalink", 29, 0, + NULL, &_interlan_obj +}, +_ulana_obj = { + "ulana", 30, 0, + NULL, &_vitalink_obj +}, +_nswc_obj = { + "nswc", 31, 0, + NULL, &_ulana_obj +}, +_santacruzoperation_obj = { + "santacruzoperation", 32, 0, + NULL, &_nswc_obj +}, +_xyplex_obj = { + "xyplex", 33, 0, + NULL, &_santacruzoperation_obj +}, +_cray_obj = { + "cray", 34, 0, + NULL, &_xyplex_obj +}, +_bellnorthernresearch_obj = { + "bellnorthernresearch", 35, 0, + NULL, &_cray_obj +}, +_dec_obj = { + "dec", 36, 0, + NULL, &_bellnorthernresearch_obj +}, +_touch_obj = { + "touch", 37, 0, + NULL, &_dec_obj +}, +_networkresearchcorp_obj = { + "networkresearchcorp", 38, 0, + NULL, &_touch_obj +}, +_baylor_obj = { + "baylor", 39, 0, + NULL, &_networkresearchcorp_obj +}, +_nmfeccllnl_obj = { + "nmfeccllnl", 40, 0, + NULL, &_baylor_obj +}, +_sri_obj = { + "sri", 41, 0, + NULL, &_nmfeccllnl_obj +}, +_sun_obj = { + "sun", 42, 0, + NULL, &_sri_obj +}, +_3com_obj = { + "3com", 43, 0, + NULL, &_sun_obj +}, +_cmc_obj = { + "cmc", 44, 0, + NULL, &_3com_obj +}, +_synoptics_obj = { + "synoptics", 45, 0, + NULL, &_cmc_obj +}, +_cheyenne_obj = { + "cheyenne", 46, 0, + NULL, &_synoptics_obj +}, +_prime_obj = { + "prime", 47, 0, + NULL, &_cheyenne_obj +}, +_mcnc_obj = { + "mcnc", 48, 0, + NULL, &_prime_obj +}, +_chipcom_obj = { + "chipcom", 49, 0, + NULL, &_mcnc_obj +}, +_opticaldatasystems_obj = { + "opticaldatasystems", 50, 0, + NULL, &_chipcom_obj +}, +_gated_obj = { + "gated", 51, 0, + NULL, &_opticaldatasystems_obj +}, +_cabletron_obj = { + "cabletron", 52, 0, + NULL, &_gated_obj +}, +_apollo_obj = { + "apollo", 53, 0, + NULL, &_cabletron_obj +}, +_desktalksystems_obj = { + "desktalksystems", 54, 0, + NULL, &_apollo_obj +}, +_ssds_obj = { + "ssds", 55, 0, + NULL, &_desktalksystems_obj +}, +_castlerock_obj = { + "castlerock", 56, 0, + NULL, &_ssds_obj +}, +_mips_obj = { + "mips", 57, 0, + NULL, &_castlerock_obj +}, +_tgv_obj = { + "tgv", 58, 0, + NULL, &_mips_obj +}, +_silicongraphics_obj = { + "silicongraphics", 59, 0, + NULL, &_tgv_obj +}, +_ubc_obj = { + "ubc", 60, 0, + NULL, &_silicongraphics_obj +}, +_merit_obj = { + "merit", 61, 0, + NULL, &_ubc_obj +}, +_fibercom_obj = { + "fibercom", 62, 0, + NULL, &_merit_obj +}, +_apple_obj = { + "apple", 63, 0, + NULL, &_fibercom_obj +}, +_gandalf_obj = { + "gandalf", 64, 0, + NULL, &_apple_obj +}, +_dartmouth_obj = { + "dartmouth", 65, 0, + NULL, &_gandalf_obj +}, +_davidsystems_obj = { + "davidsystems", 66, 0, + NULL, &_dartmouth_obj +}, +_reuter_obj = { + "reuter", 67, 0, + NULL, &_davidsystems_obj +}, +_cornell_obj = { + "cornell", 68, 0, + NULL, &_reuter_obj +}, +_tmac_obj = { + "tmac", 69, 0, + NULL, &_cornell_obj +}, +_locus_obj = { + "locus", 70, 0, + NULL, &_tmac_obj +}, +_nasa_obj = { + "nasa", 71, 0, + NULL, &_locus_obj +}, +_retix_obj = { + "retix", 72, 0, + NULL, &_nasa_obj +}, +_boeing_obj = { + "boeing", 73, 0, + NULL, &_retix_obj +}, +_att_obj = { + "att", 74, 0, + NULL, &_boeing_obj +}, +_ungermannbass_obj = { + "ungermannbass", 75, 0, + NULL, &_att_obj +}, +_digitalanalysis_obj = { + "digitalanalysis", 76, 0, + NULL, &_ungermannbass_obj +}, +_hplanman_obj = { + "hplanman", 77, 0, + NULL, &_digitalanalysis_obj +}, +_netlabs_obj = { + "netlabs", 78, 0, + NULL, &_hplanman_obj +}, +_icl_obj = { + "icl", 79, 0, + NULL, &_netlabs_obj +}, +_auspex_obj = { + "auspex", 80, 0, + NULL, &_icl_obj +}, +_lannet_obj = { + "lannet", 81, 0, + NULL, &_auspex_obj +}, +_ncd_obj = { + "ncd", 82, 0, + NULL, &_lannet_obj +}, +_raycom_obj = { + "raycom", 83, 0, + NULL, &_ncd_obj +}, +_pirellifocom_obj = { + "pirellifocom", 84, 0, + NULL, &_raycom_obj +}, +_datability_obj = { + "datability", 85, 0, + NULL, &_pirellifocom_obj +}, +_networkappltech_obj = { + "networkappltech", 86, 0, + NULL, &_datability_obj +}, +_link_obj = { + "link", 87, 0, + NULL, &_networkappltech_obj +}, +_nyu_obj = { + "nyu", 88, 0, + NULL, &_link_obj +}, +_rnd_obj = { + "rnd", 89, 0, + NULL, &_nyu_obj +}, +_intercon_obj = { + "intercon", 90, 0, + NULL, &_rnd_obj +}, +_learningtree_obj = { + "learningtree", 91, 0, + NULL, &_intercon_obj +}, +_webstercomputer_obj = { + "webstercomputer", 92, 0, + NULL, &_learningtree_obj +}, +_frontier_obj = { + "frontier", 93, 0, + NULL, &_webstercomputer_obj +}, +_nokia_obj = { + "nokia", 94, 0, + NULL, &_frontier_obj +}, +_allenbradley_obj = { + "allenbradley", 95, 0, + NULL, &_nokia_obj +}, +_cern_obj = { + "cern", 96, 0, + NULL, &_allenbradley_obj +}, +_sigma_obj = { + "sigma", 97, 0, + NULL, &_cern_obj +}, +_emergingtech_obj = { + "emergingtech", 98, 0, + NULL, &_sigma_obj +}, +_snmpresearch_obj = { + "snmpresearch", 99, 0, + NULL, &_emergingtech_obj +}, +_ohiostate_obj = { + "ohiostate", 100, 0, + NULL, &_snmpresearch_obj +}, +_ultra_obj = { + "ultra", 101, 0, + NULL, &_ohiostate_obj +}, +_ccur_obj = { + "ccur", 136, 0, + NULL, &_ultra_obj +}, +_enterprises_obj = { + "enterprises", 1, 0, + &_ccur_obj, NULL +}, +_snmpInPkts_obj = { + "snmpInPkts", 1, 0, + NULL, NULL +}, +_snmpOutPkts_obj = { + "snmpOutPkts", 2, 0, + NULL, &_snmpInPkts_obj +}, +_snmpInBadVersions_obj = { + "snmpInBadVersions", 3, 0, + NULL, &_snmpOutPkts_obj +}, +_snmpInBadCommunityNames_obj = { + "snmpInBadCommunityNames", 4, 0, + NULL, &_snmpInBadVersions_obj +}, +_snmpInBadCommunityUses_obj = { + "snmpInBadCommunityUses", 5, 0, + NULL, &_snmpInBadCommunityNames_obj +}, +_snmpInASNParseErrs_obj = { + "snmpInASNParseErrs", 6, 0, + NULL, &_snmpInBadCommunityUses_obj +}, +_snmpInBadTypes_obj = { + "snmpInBadTypes", 7, 0, + NULL, &_snmpInASNParseErrs_obj +}, +_snmpInTooBigs_obj = { + "snmpInTooBigs", 8, 0, + NULL, &_snmpInBadTypes_obj +}, +_snmpInNoSuchNames_obj = { + "snmpInNoSuchNames", 9, 0, + NULL, &_snmpInTooBigs_obj +}, +_snmpInBadValues_obj = { + "snmpInBadValues", 10, 0, + NULL, &_snmpInNoSuchNames_obj +}, +_snmpInReadOnlys_obj = { + "snmpInReadOnlys", 11, 0, + NULL, &_snmpInBadValues_obj +}, +_snmpInGenErrs_obj = { + "snmpInGenErrs", 12, 0, + NULL, &_snmpInReadOnlys_obj +}, +_snmpInTotalReqVars_obj = { + "snmpInTotalReqVars", 13, 0, + NULL, &_snmpInGenErrs_obj +}, +_snmpInTotalSetVars_obj = { + "snmpInTotalSetVars", 14, 0, + NULL, &_snmpInTotalReqVars_obj +}, +_snmpInGetRequests_obj = { + "snmpInGetRequests", 15, 0, + NULL, &_snmpInTotalSetVars_obj +}, +_snmpInGetNexts_obj = { + "snmpInGetNexts", 16, 0, + NULL, &_snmpInGetRequests_obj +}, +_snmpInSetRequests_obj = { + "snmpInSetRequests", 17, 0, + NULL, &_snmpInGetNexts_obj +}, +_snmpInGetResponses_obj = { + "snmpInGetResponses", 18, 0, + NULL, &_snmpInSetRequests_obj +}, +_snmpInTraps_obj = { + "snmpInTraps", 19, 0, + NULL, &_snmpInGetResponses_obj +}, +_snmpOutTooBigs_obj = { + "snmpOutTooBigs", 20, 0, + NULL, &_snmpInTraps_obj +}, +_snmpOutNoSuchNames_obj = { + "snmpOutNoSuchNames", 21, 0, + NULL, &_snmpOutTooBigs_obj +}, +_snmpOutBadValues_obj = { + "snmpOutBadValues", 22, 0, + NULL, &_snmpOutNoSuchNames_obj +}, +_snmpOutReadOnlys_obj = { + "snmpOutReadOnlys", 23, 0, + NULL, &_snmpOutBadValues_obj +}, +_snmpOutGenErrs_obj = { + "snmpOutGenErrs", 24, 0, + NULL, &_snmpOutReadOnlys_obj +}, +_snmpOutGetRequests_obj = { + "snmpOutGetRequests", 25, 0, + NULL, &_snmpOutGenErrs_obj +}, +_snmpOutGetNexts_obj = { + "snmpOutGetNexts", 26, 0, + NULL, &_snmpOutGetRequests_obj +}, +_snmpOutSetRequests_obj = { + "snmpOutSetRequests", 27, 0, + NULL, &_snmpOutGetNexts_obj +}, +_snmpOutGetResponses_obj = { + "snmpOutGetResponses", 28, 0, + NULL, &_snmpOutSetRequests_obj +}, +_snmpOutTraps_obj = { + "snmpOutTraps", 29, 0, + NULL, &_snmpOutGetResponses_obj +}, +_snmpEnableAuthTraps_obj = { + "snmpEnableAuthTraps", 30, 0, + NULL, &_snmpOutTraps_obj +}, +_egpNeighState_obj = { + "egpNeighState", 1, 0, + NULL, NULL +}, +_egpNeighAddr_obj = { + "egpNeighAddr", 2, 0, + NULL, &_egpNeighState_obj +}, +_egpNeighAs_obj = { + "egpNeighAs", 3, 0, + NULL, &_egpNeighAddr_obj +}, +_egpNeighInMsgs_obj = { + "egpNeighInMsgs", 4, 0, + NULL, &_egpNeighAs_obj +}, +_egpNeighInErrs_obj = { + "egpNeighInErrs", 5, 0, + NULL, &_egpNeighInMsgs_obj +}, +_egpNeighOutMsgs_obj = { + "egpNeighOutMsgs", 6, 0, + NULL, &_egpNeighInErrs_obj +}, +_egpNeighOutErrs_obj = { + "egpNeighOutErrs", 7, 0, + NULL, &_egpNeighOutMsgs_obj +}, +_egpNeighInErrMsgs_obj = { + "egpNeighInErrMsgs", 8, 0, + NULL, &_egpNeighOutErrs_obj +}, +_egpNeighOutErrMsgs_obj = { + "egpNeighOutErrMsgs", 9, 0, + NULL, &_egpNeighInErrMsgs_obj +}, +_egpNeighStateUps_obj = { + "egpNeighStateUps", 10, 0, + NULL, &_egpNeighOutErrMsgs_obj +}, +_egpNeighStateDowns_obj = { + "egpNeighStateDowns", 11, 0, + NULL, &_egpNeighStateUps_obj +}, +_egpNeighIntervalHello_obj = { + "egpNeighIntervalHello", 12, 0, + NULL, &_egpNeighStateDowns_obj +}, +_egpNeighIntervalPoll_obj = { + "egpNeighIntervalPoll", 13, 0, + NULL, &_egpNeighIntervalHello_obj +}, +_egpNeighMode_obj = { + "egpNeighMode", 14, 0, + NULL, &_egpNeighIntervalPoll_obj +}, +_egpNeighEventTrigger_obj = { + "egpNeighEventTrigger", 15, 0, + NULL, &_egpNeighMode_obj +}, +_egpNeighEntry_obj = { + "egpNeighEntry", 1, 0, + &_egpNeighEventTrigger_obj, NULL +}, +_egpInMsgs_obj = { + "egpInMsgs", 1, 0, + NULL, NULL +}, +_egpInErrors_obj = { + "egpInErrors", 2, 0, + NULL, &_egpInMsgs_obj +}, +_egpOutMsgs_obj = { + "egpOutMsgs", 3, 0, + NULL, &_egpInErrors_obj +}, +_egpOutErrors_obj = { + "egpOutErrors", 4, 0, + NULL, &_egpOutMsgs_obj +}, +_egpNeighTable_obj = { + "egpNeighTable", 5, 0, + &_egpNeighEntry_obj, &_egpOutErrors_obj +}, +_egpAs_obj = { + "egpAs", 6, 0, + NULL, &_egpNeighTable_obj +}, +_udpLocalAddress_obj = { + "udpLocalAddress", 1, 0, + NULL, NULL +}, +_udpLocalPort_obj = { + "udpLocalPort", 2, 0, + NULL, &_udpLocalAddress_obj +}, +_udpEntry_obj = { + "udpEntry", 1, 0, + &_udpLocalPort_obj, NULL +}, +_udpInDatagrams_obj = { + "udpInDatagrams", 1, 0, + NULL, NULL +}, +_udpNoPorts_obj = { + "udpNoPorts", 2, 0, + NULL, &_udpInDatagrams_obj +}, +_udpInErrors_obj = { + "udpInErrors", 3, 0, + NULL, &_udpNoPorts_obj +}, +_udpOutDatagrams_obj = { + "udpOutDatagrams", 4, 0, + NULL, &_udpInErrors_obj +}, +_udpTable_obj = { + "udpTable", 5, 0, + &_udpEntry_obj, &_udpOutDatagrams_obj +}, +_tcpConnState_obj = { + "tcpConnState", 1, 0, + NULL, NULL +}, +_tcpConnLocalAddress_obj = { + "tcpConnLocalAddress", 2, 0, + NULL, &_tcpConnState_obj +}, +_tcpConnLocalPort_obj = { + "tcpConnLocalPort", 3, 0, + NULL, &_tcpConnLocalAddress_obj +}, +_tcpConnRemAddress_obj = { + "tcpConnRemAddress", 4, 0, + NULL, &_tcpConnLocalPort_obj +}, +_tcpConnRemPort_obj = { + "tcpConnRemPort", 5, 0, + NULL, &_tcpConnRemAddress_obj +}, +_tcpConnEntry_obj = { + "tcpConnEntry", 1, 0, + &_tcpConnRemPort_obj, NULL +}, +_tcpRtoAlgorithm_obj = { + "tcpRtoAlgorithm", 1, 0, + NULL, NULL +}, +_tcpRtoMin_obj = { + "tcpRtoMin", 2, 0, + NULL, &_tcpRtoAlgorithm_obj +}, +_tcpRtoMax_obj = { + "tcpRtoMax", 3, 0, + NULL, &_tcpRtoMin_obj +}, +_tcpMaxConn_obj = { + "tcpMaxConn", 4, 0, + NULL, &_tcpRtoMax_obj +}, +_tcpActiveOpens_obj = { + "tcpActiveOpens", 5, 0, + NULL, &_tcpMaxConn_obj +}, +_tcpPassiveOpens_obj = { + "tcpPassiveOpens", 6, 0, + NULL, &_tcpActiveOpens_obj +}, +_tcpAttemptFails_obj = { + "tcpAttemptFails", 7, 0, + NULL, &_tcpPassiveOpens_obj +}, +_tcpEstabResets_obj = { + "tcpEstabResets", 8, 0, + NULL, &_tcpAttemptFails_obj +}, +_tcpCurrEstab_obj = { + "tcpCurrEstab", 9, 0, + NULL, &_tcpEstabResets_obj +}, +_tcpInSegs_obj = { + "tcpInSegs", 10, 0, + NULL, &_tcpCurrEstab_obj +}, +_tcpOutSegs_obj = { + "tcpOutSegs", 11, 0, + NULL, &_tcpInSegs_obj +}, +_tcpRetransSegs_obj = { + "tcpRetransSegs", 12, 0, + NULL, &_tcpOutSegs_obj +}, +_tcpConnTable_obj = { + "tcpConnTable", 13, 0, + &_tcpConnEntry_obj, &_tcpRetransSegs_obj +}, +_tcpInErrs_obj = { + "tcpInErrs", 14, 0, + NULL, &_tcpConnTable_obj +}, +_tcpOutRsts_obj = { + "tcpOutRsts", 15, 0, + NULL, &_tcpInErrs_obj +}, +_icmpInMsgs_obj = { + "icmpInMsgs", 1, 0, + NULL, NULL +}, +_icmpInErrors_obj = { + "icmpInErrors", 2, 0, + NULL, &_icmpInMsgs_obj +}, +_icmpInDestUnreachs_obj = { + "icmpInDestUnreachs", 3, 0, + NULL, &_icmpInErrors_obj +}, +_icmpInTimeExcds_obj = { + "icmpInTimeExcds", 4, 0, + NULL, &_icmpInDestUnreachs_obj +}, +_icmpInParmProbs_obj = { + "icmpInParmProbs", 5, 0, + NULL, &_icmpInTimeExcds_obj +}, +_icmpInSrcQuenchs_obj = { + "icmpInSrcQuenchs", 6, 0, + NULL, &_icmpInParmProbs_obj +}, +_icmpInRedirects_obj = { + "icmpInRedirects", 7, 0, + NULL, &_icmpInSrcQuenchs_obj +}, +_icmpInEchos_obj = { + "icmpInEchos", 8, 0, + NULL, &_icmpInRedirects_obj +}, +_icmpInEchoReps_obj = { + "icmpInEchoReps", 9, 0, + NULL, &_icmpInEchos_obj +}, +_icmpInTimestamps_obj = { + "icmpInTimestamps", 10, 0, + NULL, &_icmpInEchoReps_obj +}, +_icmpInTimestampReps_obj = { + "icmpInTimestampReps", 11, 0, + NULL, &_icmpInTimestamps_obj +}, +_icmpInAddrMasks_obj = { + "icmpInAddrMasks", 12, 0, + NULL, &_icmpInTimestampReps_obj +}, +_icmpInAddrMaskReps_obj = { + "icmpInAddrMaskReps", 13, 0, + NULL, &_icmpInAddrMasks_obj +}, +_icmpOutMsgs_obj = { + "icmpOutMsgs", 14, 0, + NULL, &_icmpInAddrMaskReps_obj +}, +_icmpOutErrors_obj = { + "icmpOutErrors", 15, 0, + NULL, &_icmpOutMsgs_obj +}, +_icmpOutDestUnreachs_obj = { + "icmpOutDestUnreachs", 16, 0, + NULL, &_icmpOutErrors_obj +}, +_icmpOutTimeExcds_obj = { + "icmpOutTimeExcds", 17, 0, + NULL, &_icmpOutDestUnreachs_obj +}, +_icmpOutParmProbs_obj = { + "icmpOutParmProbs", 18, 0, + NULL, &_icmpOutTimeExcds_obj +}, +_icmpOutSrcQuenchs_obj = { + "icmpOutSrcQuenchs", 19, 0, + NULL, &_icmpOutParmProbs_obj +}, +_icmpOutRedirects_obj = { + "icmpOutRedirects", 20, 0, + NULL, &_icmpOutSrcQuenchs_obj +}, +_icmpOutEchos_obj = { + "icmpOutEchos", 21, 0, + NULL, &_icmpOutRedirects_obj +}, +_icmpOutEchoReps_obj = { + "icmpOutEchoReps", 22, 0, + NULL, &_icmpOutEchos_obj +}, +_icmpOutTimestamps_obj = { + "icmpOutTimestamps", 23, 0, + NULL, &_icmpOutEchoReps_obj +}, +_icmpOutTimestampReps_obj = { + "icmpOutTimestampReps", 24, 0, + NULL, &_icmpOutTimestamps_obj +}, +_icmpOutAddrMasks_obj = { + "icmpOutAddrMasks", 25, 0, + NULL, &_icmpOutTimestampReps_obj +}, +_icmpOutAddrMaskReps_obj = { + "icmpOutAddrMaskReps", 26, 0, + NULL, &_icmpOutAddrMasks_obj +}, +_ipNetToMediaIfIndex_obj = { + "ipNetToMediaIfIndex", 1, 0, + NULL, NULL +}, +_ipNetToMediaPhysAddress_obj = { + "ipNetToMediaPhysAddress", 2, 0, + NULL, &_ipNetToMediaIfIndex_obj +}, +_ipNetToMediaNetAddress_obj = { + "ipNetToMediaNetAddress", 3, 0, + NULL, &_ipNetToMediaPhysAddress_obj +}, +_ipNetToMediaType_obj = { + "ipNetToMediaType", 4, 0, + NULL, &_ipNetToMediaNetAddress_obj +}, +_ipNetToMediaEntry_obj = { + "ipNetToMediaEntry", 1, 0, + &_ipNetToMediaType_obj, NULL +}, +_ipRouteDest_obj = { + "ipRouteDest", 1, 0, + NULL, NULL +}, +_ipRouteIfIndex_obj = { + "ipRouteIfIndex", 2, 0, + NULL, &_ipRouteDest_obj +}, +_ipRouteMetric1_obj = { + "ipRouteMetric1", 3, 0, + NULL, &_ipRouteIfIndex_obj +}, +_ipRouteMetric2_obj = { + "ipRouteMetric2", 4, 0, + NULL, &_ipRouteMetric1_obj +}, +_ipRouteMetric3_obj = { + "ipRouteMetric3", 5, 0, + NULL, &_ipRouteMetric2_obj +}, +_ipRouteMetric4_obj = { + "ipRouteMetric4", 6, 0, + NULL, &_ipRouteMetric3_obj +}, +_ipRouteNextHop_obj = { + "ipRouteNextHop", 7, 0, + NULL, &_ipRouteMetric4_obj +}, +_ipRouteType_obj = { + "ipRouteType", 8, 0, + NULL, &_ipRouteNextHop_obj +}, +_ipRouteProto_obj = { + "ipRouteProto", 9, 0, + NULL, &_ipRouteType_obj +}, +_ipRouteAge_obj = { + "ipRouteAge", 10, 0, + NULL, &_ipRouteProto_obj +}, +_ipRouteMask_obj = { + "ipRouteMask", 11, 0, + NULL, &_ipRouteAge_obj +}, +_ipRouteEntry_obj = { + "ipRouteEntry", 1, 0, + &_ipRouteMask_obj, NULL +}, +_ipAdEntAddr_obj = { + "ipAdEntAddr", 1, 0, + NULL, NULL +}, +_ipAdEntIfIndex_obj = { + "ipAdEntIfIndex", 2, 0, + NULL, &_ipAdEntAddr_obj +}, +_ipAdEntNetMask_obj = { + "ipAdEntNetMask", 3, 0, + NULL, &_ipAdEntIfIndex_obj +}, +_ipAdEntBcastAddr_obj = { + "ipAdEntBcastAddr", 4, 0, + NULL, &_ipAdEntNetMask_obj +}, +_ipAdEntReasmMaxSize_obj = { + "ipAdEntReasmMaxSize", 5, 0, + NULL, &_ipAdEntBcastAddr_obj +}, +_ipAddrEntry_obj = { + "ipAddrEntry", 1, 0, + &_ipAdEntReasmMaxSize_obj, NULL +}, +_ipForwarding_obj = { + "ipForwarding", 1, 0, + NULL, NULL +}, +_ipDefaultTTL_obj = { + "ipDefaultTTL", 2, 0, + NULL, &_ipForwarding_obj +}, +_ipInReceives_obj = { + "ipInReceives", 3, 0, + NULL, &_ipDefaultTTL_obj +}, +_ipInHdrErrors_obj = { + "ipInHdrErrors", 4, 0, + NULL, &_ipInReceives_obj +}, +_ipInAddrErrors_obj = { + "ipInAddrErrors", 5, 0, + NULL, &_ipInHdrErrors_obj +}, +_ipForwDatagrams_obj = { + "ipForwDatagrams", 6, 0, + NULL, &_ipInAddrErrors_obj +}, +_ipInUnknownProtos_obj = { + "ipInUnknownProtos", 7, 0, + NULL, &_ipForwDatagrams_obj +}, +_ipInDiscards_obj = { + "ipInDiscards", 8, 0, + NULL, &_ipInUnknownProtos_obj +}, +_ipInDelivers_obj = { + "ipInDelivers", 9, 0, + NULL, &_ipInDiscards_obj +}, +_ipOutRequests_obj = { + "ipOutRequests", 10, 0, + NULL, &_ipInDelivers_obj +}, +_ipOutDiscards_obj = { + "ipOutDiscards", 11, 0, + NULL, &_ipOutRequests_obj +}, +_ipOutNoRoutes_obj = { + "ipOutNoRoutes", 12, 0, + NULL, &_ipOutDiscards_obj +}, +_ipReasmTimeout_obj = { + "ipReasmTimeout", 13, 0, + NULL, &_ipOutNoRoutes_obj +}, +_ipReasmReqds_obj = { + "ipReasmReqds", 14, 0, + NULL, &_ipReasmTimeout_obj +}, +_ipReasmOKs_obj = { + "ipReasmOKs", 15, 0, + NULL, &_ipReasmReqds_obj +}, +_ipReasmFails_obj = { + "ipReasmFails", 16, 0, + NULL, &_ipReasmOKs_obj +}, +_ipFragOKs_obj = { + "ipFragOKs", 17, 0, + NULL, &_ipReasmFails_obj +}, +_ipFragFails_obj = { + "ipFragFails", 18, 0, + NULL, &_ipFragOKs_obj +}, +_ipFragCreates_obj = { + "ipFragCreates", 19, 0, + NULL, &_ipFragFails_obj +}, +_ipAddrTable_obj = { + "ipAddrTable", 20, 0, + &_ipAddrEntry_obj, &_ipFragCreates_obj +}, +_ipRoutingTable_obj = { + "ipRoutingTable", 21, 0, + &_ipRouteEntry_obj, &_ipAddrTable_obj +}, +_ipNetToMediaTable_obj = { + "ipNetToMediaTable", 22, 0, + &_ipNetToMediaEntry_obj, &_ipRoutingTable_obj +}, +_atIfIndex_obj = { + "atIfIndex", 1, 0, + NULL, NULL +}, +_atPhysAddress_obj = { + "atPhysAddress", 2, 0, + NULL, &_atIfIndex_obj +}, +_atNetAddress_obj = { + "atNetAddress", 3, 0, + NULL, &_atPhysAddress_obj +}, +_atEntry_obj = { + "atEntry", 1, 0, + &_atNetAddress_obj, NULL +}, +_atTable_obj = { + "atTable", 1, 0, + &_atEntry_obj, NULL +}, +_ifIndex_obj = { + "ifIndex", 1, 0, + NULL, NULL +}, +_ifDescr_obj = { + "ifDescr", 2, 0, + NULL, &_ifIndex_obj +}, +_ifType_obj = { + "ifType", 3, 0, + NULL, &_ifDescr_obj +}, +_ifMtu_obj = { + "ifMtu", 4, 0, + NULL, &_ifType_obj +}, +_ifSpeed_obj = { + "ifSpeed", 5, 0, + NULL, &_ifMtu_obj +}, +_ifPhysAddress_obj = { + "ifPhysAddress", 6, 0, + NULL, &_ifSpeed_obj +}, +_ifAdminStatus_obj = { + "ifAdminStatus", 7, 0, + NULL, &_ifPhysAddress_obj +}, +_ifOperStatus_obj = { + "ifOperStatus", 8, 0, + NULL, &_ifAdminStatus_obj +}, +_ifLastChange_obj = { + "ifLastChange", 9, 0, + NULL, &_ifOperStatus_obj +}, +_ifInOctets_obj = { + "ifInOctets", 10, 0, + NULL, &_ifLastChange_obj +}, +_ifInUcastPkts_obj = { + "ifInUcastPkts", 11, 0, + NULL, &_ifInOctets_obj +}, +_ifInNUcastPkts_obj = { + "ifInNUcastPkts", 12, 0, + NULL, &_ifInUcastPkts_obj +}, +_ifInDiscards_obj = { + "ifInDiscards", 13, 0, + NULL, &_ifInNUcastPkts_obj +}, +_ifInErrors_obj = { + "ifInErrors", 14, 0, + NULL, &_ifInDiscards_obj +}, +_ifInUnknownProtos_obj = { + "ifInUnknownProtos", 15, 0, + NULL, &_ifInErrors_obj +}, +_ifOutOctets_obj = { + "ifOutOctets", 16, 0, + NULL, &_ifInUnknownProtos_obj +}, +_ifOutUcastPkts_obj = { + "ifOutUcastPkts", 17, 0, + NULL, &_ifOutOctets_obj +}, +_ifOutNUcastPkts_obj = { + "ifOutNUcastPkts", 18, 0, + NULL, &_ifOutUcastPkts_obj +}, +_ifOutDiscards_obj = { + "ifOutDiscards", 19, 0, + NULL, &_ifOutNUcastPkts_obj +}, +_ifOutErrors_obj = { + "ifOutErrors", 20, 0, + NULL, &_ifOutDiscards_obj +}, +_ifOutQLen_obj = { + "ifOutQLen", 21, 0, + NULL, &_ifOutErrors_obj +}, +_ifSpecific_obj = { + "ifSpecific", 22, 0, + NULL, &_ifOutQLen_obj +}, +_ifEntry_obj = { + "ifEntry", 1, 0, + &_ifSpecific_obj, NULL +}, +_ifNumber_obj = { + "ifNumber", 1, 0, + NULL, NULL +}, +_ifTable_obj = { + "ifTable", 2, 0, + &_ifEntry_obj, &_ifNumber_obj +}, +_sysDescr_obj = { + "sysDescr", 1, 0, + NULL, NULL +}, +_sysObjectID_obj = { + "sysObjectID", 2, 0, + NULL, &_sysDescr_obj +}, +_sysUpTime_obj = { + "sysUpTime", 3, 0, + NULL, &_sysObjectID_obj +}, +_sysContact_obj = { + "sysContact", 4, 0, + NULL, &_sysUpTime_obj +}, +_sysName_obj = { + "sysName", 5, 0, + NULL, &_sysContact_obj +}, +_sysLocation_obj = { + "sysLocation", 6, 0, + NULL, &_sysName_obj +}, +_sysServices_obj = { + "sysServices", 7, 0, + NULL, &_sysLocation_obj +}, +_system_obj = { + "system", 1, 0, + &_sysServices_obj, NULL +}, +_interfaces_obj = { + "interfaces", 2, 0, + &_ifTable_obj, &_system_obj +}, +_at_obj = { + "at", 3, 0, + &_atTable_obj, &_interfaces_obj +}, +_ip_obj = { + "ip", 4, 0, + &_ipNetToMediaTable_obj, &_at_obj +}, +_icmp_obj = { + "icmp", 5, 0, + &_icmpOutAddrMaskReps_obj, &_ip_obj +}, +_tcp_obj = { + "tcp", 6, 0, + &_tcpOutRsts_obj, &_icmp_obj +}, +_udp_obj = { + "udp", 7, 0, + &_udpTable_obj, &_tcp_obj +}, +_egp_obj = { + "egp", 8, 0, + &_egpAs_obj, &_udp_obj +}, +_transmission_obj = { + "transmission", 10, 0, + NULL, &_egp_obj +}, +_snmp_obj = { + "snmp", 11, 0, + &_snmpEnableAuthTraps_obj, &_transmission_obj +}, +_mib_obj = { + "mib", 1, 0, + &_snmp_obj, NULL +}, +_directory_obj = { + "directory", 1, 0, + NULL, NULL +}, +_mgmt_obj = { + "mgmt", 2, 0, + &_mib_obj, &_directory_obj +}, +_experimental_obj = { + "experimental", 3, 0, + NULL, &_mgmt_obj +}, +_private_obj = { + "private", 4, 0, + &_enterprises_obj, &_experimental_obj +}, +_internet_obj = { + "internet", 1, 0, + &_private_obj, NULL +}, +_dod_obj = { + "dod", 6, 0, + &_internet_obj, NULL +}, +_org_obj = { + "org", 3, 0, + &_dod_obj, NULL +}, +_iso_obj = { + "iso", 1, 0, + &_org_obj, NULL +}, +*mibroot = &_iso_obj; diff --git a/tcpdump.tproj/netbios.h b/tcpdump.tproj/netbios.h new file mode 100644 index 0000000..629e5a5 --- /dev/null +++ b/tcpdump.tproj/netbios.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * NETBIOS protocol formats + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/netbios.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ + */ + +struct p8022Hdr { + u_char dsap; + u_char ssap; + u_char flags; +}; + +#define p8022Size 3 /* min 802.2 header size */ + +#define UI 0x03 /* 802.2 flags */ + diff --git a/tcpdump.tproj/nfs.h b/tcpdump.tproj/nfs.h new file mode 100644 index 0000000..a45e1ce --- /dev/null +++ b/tcpdump.tproj/nfs.h @@ -0,0 +1,470 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: nfs.h,v 1.2 1996/07/13 11:01:12 mickey Exp $ */ +/* $NetBSD: nfs.h,v 1.1 1996/05/23 22:49:53 fvdl Exp $ */ + +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsproto.h 8.2 (Berkeley) 3/30/95 + */ + +/* + * nfs definitions as per the Version 2 and 3 specs + */ + +/* + * Constants as defined in the Sun NFS Version 2 and 3 specs. + * "NFS: Network File System Protocol Specification" RFC1094 + * and in the "NFS: Network File System Version 3 Protocol + * Specification" + */ + +#define NFS_PORT 2049 +#define NFS_PROG 100003 +#define NFS_VER2 2 +#define NFS_VER3 3 +#define NFS_V2MAXDATA 8192 +#define NFS_MAXDGRAMDATA 16384 +#define NFS_MAXDATA 32768 +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_MAXPKTHDR 404 +#define NFS_MAXPACKET (NFS_MAXPKTHDR + NFS_MAXDATA) +#define NFS_MINPACKET 20 +#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */ + +/* Stat numbers for rpc returns (version 2 and 3) */ +#define NFS_OK 0 +#define NFSERR_PERM 1 +#define NFSERR_NOENT 2 +#define NFSERR_IO 5 +#define NFSERR_NXIO 6 +#define NFSERR_ACCES 13 +#define NFSERR_EXIST 17 +#define NFSERR_XDEV 18 /* Version 3 only */ +#define NFSERR_NODEV 19 +#define NFSERR_NOTDIR 20 +#define NFSERR_ISDIR 21 +#define NFSERR_INVAL 22 /* Version 3 only */ +#define NFSERR_FBIG 27 +#define NFSERR_NOSPC 28 +#define NFSERR_ROFS 30 +#define NFSERR_MLINK 31 /* Version 3 only */ +#define NFSERR_NAMETOL 63 +#define NFSERR_NOTEMPTY 66 +#define NFSERR_DQUOT 69 +#define NFSERR_STALE 70 +#define NFSERR_REMOTE 71 /* Version 3 only */ +#define NFSERR_WFLUSH 99 /* Version 2 only */ +#define NFSERR_BADHANDLE 10001 /* The rest Version 3 only */ +#define NFSERR_NOT_SYNC 10002 +#define NFSERR_BAD_COOKIE 10003 +#define NFSERR_NOTSUPP 10004 +#define NFSERR_TOOSMALL 10005 +#define NFSERR_SERVERFAULT 10006 +#define NFSERR_BADTYPE 10007 +#define NFSERR_JUKEBOX 10008 +#define NFSERR_TRYLATER NFSERR_JUKEBOX +#define NFSERR_STALEWRITEVERF 30001 /* Fake return for nfs_commit() */ + +#define NFSERR_RETVOID 0x20000000 /* Return void, not error */ +#define NFSERR_AUTHERR 0x40000000 /* Mark an authentication error */ +#define NFSERR_RETERR 0x80000000 /* Mark an error return for V3 */ + +/* Sizes in bytes of various nfs rpc components */ +#define NFSX_UNSIGNED 4 + +/* specific to NFS Version 2 */ +#define NFSX_V2FH 32 +#define NFSX_V2FATTR 68 +#define NFSX_V2SATTR 32 +#define NFSX_V2COOKIE 4 +#define NFSX_V2STATFS 20 + +/* specific to NFS Version 3 */ +#if 0 +#define NFSX_V3FH (sizeof (fhandle_t)) /* size this server uses */ +#endif +#define NFSX_V3FHMAX 64 /* max. allowed by protocol */ +#define NFSX_V3FATTR 84 +#define NFSX_V3SATTR 60 /* max. all fields filled in */ +#define NFSX_V3SRVSATTR (sizeof (struct nfsv3_sattr)) +#define NFSX_V3POSTOPATTR (NFSX_V3FATTR + NFSX_UNSIGNED) +#define NFSX_V3WCCDATA (NFSX_V3POSTOPATTR + 8 * NFSX_UNSIGNED) +#define NFSX_V3COOKIEVERF 8 +#define NFSX_V3WRITEVERF 8 +#define NFSX_V3CREATEVERF 8 +#define NFSX_V3STATFS 52 +#define NFSX_V3FSINFO 48 +#define NFSX_V3PATHCONF 24 + +/* variants for both versions */ +#define NFSX_FH(v3) ((v3) ? (NFSX_V3FHMAX + NFSX_UNSIGNED) : \ + NFSX_V2FH) +#define NFSX_SRVFH(v3) ((v3) ? NFSX_V3FH : NFSX_V2FH) +#define NFSX_FATTR(v3) ((v3) ? NFSX_V3FATTR : NFSX_V2FATTR) +#define NFSX_PREOPATTR(v3) ((v3) ? (7 * NFSX_UNSIGNED) : 0) +#define NFSX_POSTOPATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : 0) +#define NFSX_POSTOPORFATTR(v3) ((v3) ? (NFSX_V3FATTR + NFSX_UNSIGNED) : \ + NFSX_V2FATTR) +#define NFSX_WCCDATA(v3) ((v3) ? NFSX_V3WCCDATA : 0) +#define NFSX_WCCORFATTR(v3) ((v3) ? NFSX_V3WCCDATA : NFSX_V2FATTR) +#define NFSX_SATTR(v3) ((v3) ? NFSX_V3SATTR : NFSX_V2SATTR) +#define NFSX_COOKIEVERF(v3) ((v3) ? NFSX_V3COOKIEVERF : 0) +#define NFSX_WRITEVERF(v3) ((v3) ? NFSX_V3WRITEVERF : 0) +#define NFSX_READDIR(v3) ((v3) ? (5 * NFSX_UNSIGNED) : \ + (2 * NFSX_UNSIGNED)) +#define NFSX_STATFS(v3) ((v3) ? NFSX_V3STATFS : NFSX_V2STATFS) + +/* nfs rpc procedure numbers (before version mapping) */ +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_LOOKUP 3 +#define NFSPROC_ACCESS 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITE 7 +#define NFSPROC_CREATE 8 +#define NFSPROC_MKDIR 9 +#define NFSPROC_SYMLINK 10 +#define NFSPROC_MKNOD 11 +#define NFSPROC_REMOVE 12 +#define NFSPROC_RMDIR 13 +#define NFSPROC_RENAME 14 +#define NFSPROC_LINK 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_READDIRPLUS 17 +#define NFSPROC_FSSTAT 18 +#define NFSPROC_FSINFO 19 +#define NFSPROC_PATHCONF 20 +#define NFSPROC_COMMIT 21 + +/* And leasing (nqnfs) procedure numbers (must be last) */ +#define NQNFSPROC_GETLEASE 22 +#define NQNFSPROC_VACATED 23 +#define NQNFSPROC_EVICTED 24 + +#define NFSPROC_NOOP 25 +#define NFS_NPROCS 26 + +/* Actual Version 2 procedure numbers */ +#define NFSV2PROC_NULL 0 +#define NFSV2PROC_GETATTR 1 +#define NFSV2PROC_SETATTR 2 +#define NFSV2PROC_NOOP 3 +#define NFSV2PROC_ROOT NFSV2PROC_NOOP /* Obsolete */ +#define NFSV2PROC_LOOKUP 4 +#define NFSV2PROC_READLINK 5 +#define NFSV2PROC_READ 6 +#define NFSV2PROC_WRITECACHE NFSV2PROC_NOOP /* Obsolete */ +#define NFSV2PROC_WRITE 8 +#define NFSV2PROC_CREATE 9 +#define NFSV2PROC_REMOVE 10 +#define NFSV2PROC_RENAME 11 +#define NFSV2PROC_LINK 12 +#define NFSV2PROC_SYMLINK 13 +#define NFSV2PROC_MKDIR 14 +#define NFSV2PROC_RMDIR 15 +#define NFSV2PROC_READDIR 16 +#define NFSV2PROC_STATFS 17 + +/* + * Constants used by the Version 3 protocol for various RPCs + */ +#define NFSV3SATTRTIME_DONTCHANGE 0 +#define NFSV3SATTRTIME_TOSERVER 1 +#define NFSV3SATTRTIME_TOCLIENT 2 + +#define NFSV3ATTRTIME_NMODES 3 + +#define NFSV3ACCESS_READ 0x01 +#define NFSV3ACCESS_LOOKUP 0x02 +#define NFSV3ACCESS_MODIFY 0x04 +#define NFSV3ACCESS_EXTEND 0x08 +#define NFSV3ACCESS_DELETE 0x10 +#define NFSV3ACCESS_EXECUTE 0x20 + +#define NFSV3WRITE_UNSTABLE 0 +#define NFSV3WRITE_DATASYNC 1 +#define NFSV3WRITE_FILESYNC 2 + +#define NFSV3WRITE_NMODES 3 + +#define NFSV3CREATE_UNCHECKED 0 +#define NFSV3CREATE_GUARDED 1 +#define NFSV3CREATE_EXCLUSIVE 2 + +#define NFSV3CREATE_NMODES 3 + +#define NFSV3FSINFO_LINK 0x01 +#define NFSV3FSINFO_SYMLINK 0x02 +#define NFSV3FSINFO_HOMOGENEOUS 0x08 +#define NFSV3FSINFO_CANSETTIME 0x10 + +/* Conversion macros */ +#define vtonfsv2_mode(t,m) \ + txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \ + MAKEIMODE((t), (m))) +#define vtonfsv3_mode(m) txdr_unsigned((m) & 07777) +#define nfstov_mode(a) (fxdr_unsigned(u_int16_t, (a))&07777) +#define vtonfsv2_type(a) txdr_unsigned(nfsv2_type[((int32_t)(a))]) +#define vtonfsv3_type(a) txdr_unsigned(nfsv3_type[((int32_t)(a))]) +#define nfsv2tov_type(a) nv2tov_type[fxdr_unsigned(u_int32,(a))&0x7] +#define nfsv3tov_type(a) nv3tov_type[fxdr_unsigned(u_int32,(a))&0x7] + +/* File types */ +typedef enum { NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5, + NFSOCK=6, NFFIFO=7 } nfstype; + +/* Structs for common parts of the rpc's */ +/* + * File Handle (32 bytes for version 2), variable up to 64 for version 3. + * File Handles of up to NFS_SMALLFH in size are stored directly in the + * nfs node, whereas larger ones are malloc'd. (This never happens when + * NFS_SMALLFH is set to 64.) + * NFS_SMALLFH should be in the range of 32 to 64 and be divisible by 4. + */ +#ifndef NFS_SMALLFH +#define NFS_SMALLFH 64 +#endif +union nfsfh { +/* fhandle_t fh_generic; */ + u_char fh_bytes[NFS_SMALLFH]; +}; +typedef union nfsfh nfsfh_t; + +struct nfsv2_time { + u_int32 nfsv2_sec; + u_int32 nfsv2_usec; +}; +typedef struct nfsv2_time nfstime2; + +struct nfsv3_time { + u_int32 nfsv3_sec; + u_int32 nfsv3_nsec; +}; +typedef struct nfsv3_time nfstime3; + +/* + * Quads are defined as arrays of 2 longs to ensure dense packing for the + * protocol and to facilitate xdr conversion. + */ +struct nfs_uquad { + u_int32 nfsuquad[2]; +}; +typedef struct nfs_uquad nfsuint64; + +/* + * Used to convert between two u_longs and a u_quad_t. + */ +union nfs_quadconvert { + u_int32 lval[2]; + u_quad_t qval; +}; +typedef union nfs_quadconvert nfsquad_t; + +/* + * NFS Version 3 special file number. + */ +struct nfsv3_spec { + u_int32 specdata1; + u_int32 specdata2; +}; +typedef struct nfsv3_spec nfsv3spec; + +/* + * File attributes and setable attributes. These structures cover both + * NFS version 2 and the version 3 protocol. Note that the union is only + * used so that one pointer can refer to both variants. These structures + * go out on the wire and must be densely packed, so no quad data types + * are used. (all fields are longs or u_longs or structures of same) + * NB: You can't do sizeof(struct nfs_fattr), you must use the + * NFSX_FATTR(v3) macro. + */ +struct nfs_fattr { + u_int32 fa_type; + u_int32 fa_mode; + u_int32 fa_nlink; + u_int32 fa_uid; + u_int32 fa_gid; + union { + struct { + u_int32 nfsv2fa_size; + u_int32 nfsv2fa_blocksize; + u_int32 nfsv2fa_rdev; + u_int32 nfsv2fa_blocks; + u_int32 nfsv2fa_fsid; + u_int32 nfsv2fa_fileid; + nfstime2 nfsv2fa_atime; + nfstime2 nfsv2fa_mtime; + nfstime2 nfsv2fa_ctime; + } fa_nfsv2; + struct { + nfsuint64 nfsv3fa_size; + nfsuint64 nfsv3fa_used; + nfsv3spec nfsv3fa_rdev; + nfsuint64 nfsv3fa_fsid; + nfsuint64 nfsv3fa_fileid; + nfstime3 nfsv3fa_atime; + nfstime3 nfsv3fa_mtime; + nfstime3 nfsv3fa_ctime; + } fa_nfsv3; + } fa_un; +}; + +/* and some ugly defines for accessing union components */ +#define fa2_size fa_un.fa_nfsv2.nfsv2fa_size +#define fa2_blocksize fa_un.fa_nfsv2.nfsv2fa_blocksize +#define fa2_rdev fa_un.fa_nfsv2.nfsv2fa_rdev +#define fa2_blocks fa_un.fa_nfsv2.nfsv2fa_blocks +#define fa2_fsid fa_un.fa_nfsv2.nfsv2fa_fsid +#define fa2_fileid fa_un.fa_nfsv2.nfsv2fa_fileid +#define fa2_atime fa_un.fa_nfsv2.nfsv2fa_atime +#define fa2_mtime fa_un.fa_nfsv2.nfsv2fa_mtime +#define fa2_ctime fa_un.fa_nfsv2.nfsv2fa_ctime +#define fa3_size fa_un.fa_nfsv3.nfsv3fa_size +#define fa3_used fa_un.fa_nfsv3.nfsv3fa_used +#define fa3_rdev fa_un.fa_nfsv3.nfsv3fa_rdev +#define fa3_fsid fa_un.fa_nfsv3.nfsv3fa_fsid +#define fa3_fileid fa_un.fa_nfsv3.nfsv3fa_fileid +#define fa3_atime fa_un.fa_nfsv3.nfsv3fa_atime +#define fa3_mtime fa_un.fa_nfsv3.nfsv3fa_mtime +#define fa3_ctime fa_un.fa_nfsv3.nfsv3fa_ctime + +struct nfsv2_sattr { + u_int32 sa_mode; + u_int32 sa_uid; + u_int32 sa_gid; + u_int32 sa_size; + nfstime2 sa_atime; + nfstime2 sa_mtime; +}; + +/* + * NFS Version 3 sattr structure for the new node creation case. + */ +struct nfsv3_sattr { + u_int32 sa_modeset; + u_int32 sa_mode; + u_int32 sa_uidset; + u_int32 sa_uid; + u_int32 sa_gidset; + u_int32 sa_gid; + u_int32 sa_sizeset; + u_int32 sa_size; + u_int32 sa_atimetype; + nfstime3 sa_atime; + u_int32 sa_mtimetype; + nfstime3 sa_mtime; +}; + +struct nfs_statfs { + union { + struct { + u_int32 nfsv2sf_tsize; + u_int32 nfsv2sf_bsize; + u_int32 nfsv2sf_blocks; + u_int32 nfsv2sf_bfree; + u_int32 nfsv2sf_bavail; + } sf_nfsv2; + struct { + nfsuint64 nfsv3sf_tbytes; + nfsuint64 nfsv3sf_fbytes; + nfsuint64 nfsv3sf_abytes; + nfsuint64 nfsv3sf_tfiles; + nfsuint64 nfsv3sf_ffiles; + nfsuint64 nfsv3sf_afiles; + u_int32 nfsv3sf_invarsec; + } sf_nfsv3; + } sf_un; +}; + +#define sf_tsize sf_un.sf_nfsv2.nfsv2sf_tsize +#define sf_bsize sf_un.sf_nfsv2.nfsv2sf_bsize +#define sf_blocks sf_un.sf_nfsv2.nfsv2sf_blocks +#define sf_bfree sf_un.sf_nfsv2.nfsv2sf_bfree +#define sf_bavail sf_un.sf_nfsv2.nfsv2sf_bavail +#define sf_tbytes sf_un.sf_nfsv3.nfsv3sf_tbytes +#define sf_fbytes sf_un.sf_nfsv3.nfsv3sf_fbytes +#define sf_abytes sf_un.sf_nfsv3.nfsv3sf_abytes +#define sf_tfiles sf_un.sf_nfsv3.nfsv3sf_tfiles +#define sf_ffiles sf_un.sf_nfsv3.nfsv3sf_ffiles +#define sf_afiles sf_un.sf_nfsv3.nfsv3sf_afiles +#define sf_invarsec sf_un.sf_nfsv3.nfsv3sf_invarsec + +struct nfsv3_fsinfo { + u_int32 fs_rtmax; + u_int32 fs_rtpref; + u_int32 fs_rtmult; + u_int32 fs_wtmax; + u_int32 fs_wtpref; + u_int32 fs_wtmult; + u_int32 fs_dtpref; + nfsuint64 fs_maxfilesize; + nfstime3 fs_timedelta; + u_int32 fs_properties; +}; + +struct nfsv3_pathconf { + u_int32 pc_linkmax; + u_int32 pc_namemax; + u_int32 pc_notrunc; + u_int32 pc_chownrestricted; + u_int32 pc_caseinsensitive; + u_int32 pc_casepreserving; +}; diff --git a/tcpdump.tproj/nfsfh.h b/tcpdump.tproj/nfsfh.h new file mode 100644 index 0000000..f354eec --- /dev/null +++ b/tcpdump.tproj/nfsfh.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/nfsfh.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ + * + * nfsfh.h - NFS file handle definitions (for portable use) + * + * Jeffrey C. Mogul + * Digital Equipment Corporation + * Western Research Laboratory + */ + +/* + * Internal representation of dev_t, because different NFS servers + * that we might be spying upon use different external representations. + */ +typedef struct { + u_int32_t Minor; /* upper case to avoid clashing with macro names */ + u_int32_t Major; +} my_devt; + +#define dev_eq(a,b) ((a.Minor == b.Minor) && (a.Major == b.Major)) + +/* + * Many file servers now use a large file system ID. This is + * our internal representation of that. + */ +typedef struct { + my_devt Fsid_dev; /* XXX avoid name conflict with AIX */ + u_int32_t fsid_code; +} my_fsid; + +#define fsid_eq(a,b) ((a.fsid_code == b.fsid_code) &&\ + dev_eq(a.fsid_dev, b.fsid_dev)) + +extern void Parse_fh(caddr_t *, my_fsid *, ino_t *, char **, char **, int); diff --git a/tcpdump.tproj/nfsv2.h b/tcpdump.tproj/nfsv2.h new file mode 100644 index 0000000..d991ddc --- /dev/null +++ b/tcpdump.tproj/nfsv2.h @@ -0,0 +1,285 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Macklem at The University of Guelph. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)nfsv2.h 7.11 (Berkeley) 9/30/92 + */ + +/* + * nfs definitions as per the version 2 specs + */ + +/* + * Constants as defined in the Sun NFS Version 2 spec. + * "NFS: Network File System Protocol Specification" RFC1094 + */ + +#define NFS_PORT 2049 +#define NFS_PROG 100003 +#define NFS_VER2 2 +#define NFS_MAXDGRAMDATA 8192 +#define NFS_MAXDATA 32768 +#define NFS_MAXPATHLEN 1024 +#define NFS_MAXNAMLEN 255 +#define NFS_FHSIZE 32 +#define NFS_MAXPKTHDR 404 +#define NFS_MAXPACKET (NFS_MAXPKTHDR+NFS_MAXDATA) +#define NFS_MINPACKET 20 +#define NFS_FABLKSIZE 512 /* Size in bytes of a block wrt fa_blocks */ + +/* Stat numbers for rpc returns */ +#define NFS_OK 0 +#define NFSERR_PERM 1 +#define NFSERR_NOENT 2 +#define NFSERR_IO 5 +#define NFSERR_NXIO 6 +#define NFSERR_ACCES 13 +#define NFSERR_EXIST 17 +#define NFSERR_NODEV 19 +#define NFSERR_NOTDIR 20 +#define NFSERR_ISDIR 21 +#define NFSERR_FBIG 27 +#define NFSERR_NOSPC 28 +#define NFSERR_ROFS 30 +#define NFSERR_NAMETOL 63 +#define NFSERR_NOTEMPTY 66 +#define NFSERR_DQUOT 69 +#define NFSERR_STALE 70 +#define NFSERR_WFLUSH 99 + +/* Sizes in bytes of various nfs rpc components */ +#define NFSX_FH 32 +#define NFSX_UNSIGNED 4 +#define NFSX_NFSFATTR 68 +#define NFSX_NQFATTR 92 +#define NFSX_NFSSATTR 32 +#define NFSX_NQSATTR 44 +#define NFSX_COOKIE 4 +#define NFSX_NFSSTATFS 20 +#define NFSX_NQSTATFS 28 +#define NFSX_FATTR(isnq) ((isnq) ? NFSX_NQFATTR : NFSX_NFSFATTR) +#define NFSX_SATTR(isnq) ((isnq) ? NFSX_NQSATTR : NFSX_NFSSATTR) +#define NFSX_STATFS(isnq) ((isnq) ? NFSX_NQSTATFS : NFSX_NFSSTATFS) + +/* nfs rpc procedure numbers */ +#define NFSPROC_NULL 0 +#define NFSPROC_GETATTR 1 +#define NFSPROC_SETATTR 2 +#define NFSPROC_NOOP 3 +#define NFSPROC_ROOT NFSPROC_NOOP /* Obsolete */ +#define NFSPROC_LOOKUP 4 +#define NFSPROC_READLINK 5 +#define NFSPROC_READ 6 +#define NFSPROC_WRITECACHE NFSPROC_NOOP /* Obsolete */ +#define NFSPROC_WRITE 8 +#define NFSPROC_CREATE 9 +#define NFSPROC_REMOVE 10 +#define NFSPROC_RENAME 11 +#define NFSPROC_LINK 12 +#define NFSPROC_SYMLINK 13 +#define NFSPROC_MKDIR 14 +#define NFSPROC_RMDIR 15 +#define NFSPROC_READDIR 16 +#define NFSPROC_STATFS 17 + +/* NQ nfs numbers */ +#define NQNFSPROC_READDIRLOOK 18 +#define NQNFSPROC_GETLEASE 19 +#define NQNFSPROC_VACATED 20 +#define NQNFSPROC_EVICTED 21 +#define NQNFSPROC_ACCESS 22 + +#define NFS_NPROCS 23 +/* Conversion macros */ +extern int vttoif_tab[]; +#define vtonfs_mode(t,m) \ + txdr_unsigned(((t) == VFIFO) ? MAKEIMODE(VCHR, (m)) : \ + MAKEIMODE((t), (m))) +#define nfstov_mode(a) (fxdr_unsigned(u_short, (a))&07777) +#define vtonfs_type(a) txdr_unsigned(nfs_type[((int32_t)(a))]) +#define nfstov_type(a) ntov_type[fxdr_unsigned(u_int32_t,(a))&0x7] + +/* File types */ +typedef enum { + NFNON=0, NFREG=1, NFDIR=2, NFBLK=3, NFCHR=4, NFLNK=5 +} tcpdump_nfstype; + +/* Structs for common parts of the rpc's */ +struct nfsv2_time { + u_int32_t nfs_sec; + u_int32_t nfs_usec; +}; + +struct nqnfs_time { + u_int32_t nq_sec; + u_int32_t nq_nsec; +}; + +/* + * File attributes and setable attributes. These structures cover both + * NFS version 2 and the NQNFS protocol. Note that the union is only + * used to that one pointer can refer to both variants. These structures + * go out on the wire and must be densely packed, so no quad data types + * are used. (all fields are int32_t or u_int32_t's or structures of same) + * NB: You can't do sizeof(struct nfsv2_fattr), you must use the + * NFSX_FATTR(isnq) macro. + */ +struct nfsv2_fattr { + u_int32_t fa_type; + u_int32_t fa_mode; + u_int32_t fa_nlink; + u_int32_t fa_uid; + u_int32_t fa_gid; + union { + struct { + u_int32_t nfsfa_size; + u_int32_t nfsfa_blocksize; + u_int32_t nfsfa_rdev; + u_int32_t nfsfa_blocks; + u_int32_t nfsfa_fsid; + u_int32_t nfsfa_fileid; + struct nfsv2_time nfsfa_atime; + struct nfsv2_time nfsfa_mtime; + struct nfsv2_time nfsfa_ctime; + } fa_nfsv2; + struct { + struct { + u_int32_t nqfa_qsize[2]; + } nqfa_size; + u_int32_t nqfa_blocksize; + u_int32_t nqfa_rdev; + struct { + u_int32_t nqfa_qbytes[2]; + } nqfa_bytes; + u_int32_t nqfa_fsid; + u_int32_t nqfa_fileid; + struct nqnfs_time nqfa_atime; + struct nqnfs_time nqfa_mtime; + struct nqnfs_time nqfa_ctime; + u_int32_t nqfa_flags; + u_int32_t nqfa_gen; + struct { + u_int32_t nqfa_qfilerev[2]; + } nqfa_filerev; + } fa_nqnfs; + } fa_un; +}; + +/* and some ugly defines for accessing union components */ +#define fa_nfssize fa_un.fa_nfsv2.nfsfa_size +#define fa_nfsblocksize fa_un.fa_nfsv2.nfsfa_blocksize +#define fa_nfsrdev fa_un.fa_nfsv2.nfsfa_rdev +#define fa_nfsblocks fa_un.fa_nfsv2.nfsfa_blocks +#define fa_nfsfsid fa_un.fa_nfsv2.nfsfa_fsid +#define fa_nfsfileid fa_un.fa_nfsv2.nfsfa_fileid +#define fa_nfsatime fa_un.fa_nfsv2.nfsfa_atime +#define fa_nfsmtime fa_un.fa_nfsv2.nfsfa_mtime +#define fa_nfsctime fa_un.fa_nfsv2.nfsfa_ctime +#define fa_nqsize fa_un.fa_nqnfs.nqfa_size +#define fa_nqblocksize fa_un.fa_nqnfs.nqfa_blocksize +#define fa_nqrdev fa_un.fa_nqnfs.nqfa_rdev +#define fa_nqbytes fa_un.fa_nqnfs.nqfa_bytes +#define fa_nqfsid fa_un.fa_nqnfs.nqfa_fsid +#define fa_nqfileid fa_un.fa_nqnfs.nqfa_fileid +#define fa_nqatime fa_un.fa_nqnfs.nqfa_atime +#define fa_nqmtime fa_un.fa_nqnfs.nqfa_mtime +#define fa_nqctime fa_un.fa_nqnfs.nqfa_ctime +#define fa_nqflags fa_un.fa_nqnfs.nqfa_flags +#define fa_nqgen fa_un.fa_nqnfs.nqfa_gen +#define fa_nqfilerev fa_un.fa_nqnfs.nqfa_filerev + +struct nfsv2_sattr { + u_int32_t sa_mode; + u_int32_t sa_uid; + u_int32_t sa_gid; + union { + struct { + u_int32_t nfssa_size; + struct nfsv2_time nfssa_atime; + struct nfsv2_time nfssa_mtime; + } sa_nfsv2; + struct { + struct { + u_int32_t nqsa_qsize[2]; + } nqsa_size; + struct nqnfs_time nqsa_atime; + struct nqnfs_time nqsa_mtime; + u_int32_t nqsa_flags; + u_int32_t nqsa_rdev; + } sa_nqnfs; + } sa_un; +}; + +/* and some ugly defines for accessing the unions */ +#define sa_nfssize sa_un.sa_nfsv2.nfssa_size +#define sa_nfsatime sa_un.sa_nfsv2.nfssa_atime +#define sa_nfsmtime sa_un.sa_nfsv2.nfssa_mtime +#define sa_nqsize sa_un.sa_nqnfs.nqsa_size +#define sa_nqatime sa_un.sa_nqnfs.nqsa_atime +#define sa_nqmtime sa_un.sa_nqnfs.nqsa_mtime +#define sa_nqflags sa_un.sa_nqnfs.nqsa_flags +#define sa_nqrdev sa_un.sa_nqnfs.nqsa_rdev + +struct nfsv2_statfs { + u_int32_t sf_tsize; + u_int32_t sf_bsize; + u_int32_t sf_blocks; + u_int32_t sf_bfree; + u_int32_t sf_bavail; + u_int32_t sf_files; /* Nqnfs only */ + u_int32_t sf_ffree; /* ditto */ +}; diff --git a/tcpdump.tproj/ntp.h b/tcpdump.tproj/ntp.h new file mode 100644 index 0000000..dd69af9 --- /dev/null +++ b/tcpdump.tproj/ntp.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/ntp.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ */ + +/* + * Based on ntp.h from the U of MD implementation + * This file is based on Version 2 of the NTP spec (RFC1119). + */ + +/* + * Definitions for the masses + */ +#define JAN_1970 2208988800 /* 1970 - 1900 in seconds */ + +/* + * Structure definitions for NTP fixed point values + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Integer Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Fraction Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Integer Part | Fraction Part | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +struct l_fixedpt { + u_int32_t int_part; + u_int32_t fraction; +}; + +struct s_fixedpt { + u_short int_part; + u_short fraction; +}; + +/* ================= Table 3.3. Packet Variables ================= */ +/* + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |LI | VN | Mode| Stratum | Poll | Precision | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Synchronizing Distance | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Synchronizing Dispersion | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reference Clock Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Reference Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Originate Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Receive Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | | + * | Transmit Timestamp (64 bits) | + * | | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +*/ +struct ntpdata { + u_char status; /* status of local clock and leap info */ + u_char stratum; /* Stratum level */ + u_char ppoll; /* poll value */ + int precision:8; + struct s_fixedpt distance; + struct s_fixedpt dispersion; + u_int32_t refid; + struct l_fixedpt reftime; + struct l_fixedpt org; + struct l_fixedpt rec; + struct l_fixedpt xmt; +}; +/* + * Leap Second Codes (high order two bits) + */ +#define NO_WARNING 0x00 /* no warning */ +#define PLUS_SEC 0x40 /* add a second (61 seconds) */ +#define MINUS_SEC 0x80 /* minus a second (59 seconds) */ +#define ALARM 0xc0 /* alarm condition (clock unsynchronized) */ + +/* + * Clock Status Bits that Encode Version + */ +#define NTPVERSION_1 0x08 +#define VERSIONMASK 0x38 +#define LEAPMASK 0xc0 +#define MODEMASK 0x07 + +/* + * Code values + */ +#define MODE_UNSPEC 0 /* unspecified */ +#define MODE_SYM_ACT 1 /* symmetric active */ +#define MODE_SYM_PAS 2 /* symmetric passive */ +#define MODE_CLIENT 3 /* client */ +#define MODE_SERVER 4 /* server */ +#define MODE_BROADCAST 5 /* broadcast */ +#define MODE_RES1 6 /* reserved */ +#define MODE_RES2 7 /* reserved */ + +/* + * Stratum Definitions + */ +#define UNSPECIFIED 0 +#define PRIM_REF 1 /* radio clock */ +#define INFO_QUERY 62 /* **** THIS implementation dependent **** */ +#define INFO_REPLY 63 /* **** THIS implementation dependent **** */ diff --git a/tcpdump.tproj/os-solaris2.h b/tcpdump.tproj/os-solaris2.h new file mode 100644 index 0000000..440d65c --- /dev/null +++ b/tcpdump.tproj/os-solaris2.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/os-solaris2.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL) + */ + +/* Prototypes missing in SunOS 5 */ +int daemon(int, int); +int dn_expand(u_char *, u_char *, u_char *, u_char *, int); +int dn_skipname(u_char *, u_char *); +int flock(int, int); +int getdtablesize(void); +int gethostname(char *, int); +int getpagesize(void); +char *getusershell(void); +char *getwd(char *); +int iruserok(u_int, int, char *, char *); +#ifdef __STDC__ +struct utmp; +void login(struct utmp *); +#endif +int logout(const char *); +int res_query(char *, int, int, u_char *, int); +int setenv(const char *, const char *, int); +#if defined(_STDIO_H) && defined(HAVE_SETLINEBUF) +int setlinebuf(FILE *); +#endif +int sigblock(int); +int sigsetmask(int); +char *strerror(int); +int snprintf(char *, size_t, const char *, ...); +int strcasecmp(const char *, const char *); +void unsetenv(const char *); +#ifdef __STDC__ +struct timeval; +#endif +int utimes(const char *, struct timeval *); diff --git a/tcpdump.tproj/os-sunos4.h b/tcpdump.tproj/os-sunos4.h new file mode 100644 index 0000000..01389d1 --- /dev/null +++ b/tcpdump.tproj/os-sunos4.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1990, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/os-sunos4.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL) + */ + +/* Prototypes missing in SunOS 4 */ +#ifdef FILE +int _filbuf(FILE *); +int _flsbuf(u_char, FILE *); +int fclose(FILE *); +int fflush(FILE *); +int fgetc(FILE *); +int fprintf(FILE *, const char *, ...); +int fputc(int, FILE *); +int fputs(const char *, FILE *); +u_int fread(void *, u_int, u_int, FILE *); +int fseek(FILE *, long, int); +u_int fwrite(const void *, u_int, u_int, FILE *); +int pclose(FILE *); +void rewind(FILE *); +void setbuf(FILE *, char *); +int setlinebuf(FILE *); +int ungetc(int, FILE *); +int vfprintf(FILE *, const char *, ...); +int vprintf(const char *, ...); +#endif + +#if __GNUC__ <= 1 +int read(int, char *, u_int); +int write(int, char *, u_int); +#endif + +long a64l(const char *); +#ifdef __STDC__ +struct sockaddr; +#endif +int accept(int, struct sockaddr *, int *); +int bind(int, struct sockaddr *, int); +int bcmp(const void *, const void *, u_int); +void bcopy(const void *, void *, u_int); +void bzero(void *, int); +int chroot(const char *); +int close(int); +void closelog(void); +int connect(int, struct sockaddr *, int); +char *crypt(const char *, const char *); +int daemon(int, int); +int fchmod(int, int); +int fchown(int, int, int); +void endgrent(void); +void endpwent(void); +void endservent(void); +#ifdef __STDC__ +struct ether_addr; +#endif +struct ether_addr *ether_aton(const char *); +int flock(int, int); +#ifdef __STDC__ +struct stat; +#endif +int fstat(int, struct stat *); +#ifdef __STDC__ +struct statfs; +#endif +int fstatfs(int, struct statfs *); +int fsync(int); +#ifdef __STDC__ +struct timeb; +#endif +int ftime(struct timeb *); +int ftruncate(int, off_t); +int getdtablesize(void); +long gethostid(void); +int gethostname(char *, int); +int getopt(int, char * const *, const char *); +int getpagesize(void); +char *getpass(char *); +int getpeername(int, struct sockaddr *, int *); +int getpriority(int, int); +#ifdef __STDC__ +struct rlimit; +#endif +int getrlimit(int, struct rlimit *); +int getsockname(int, struct sockaddr *, int *); +int getsockopt(int, int, int, char *, int *); +#ifdef __STDC__ +struct timeval; +struct timezone; +#endif +int gettimeofday(struct timeval *, struct timezone *); +char *getusershell(void); +char *getwd(char *); +int initgroups(const char *, int); +int ioctl(int, int, caddr_t); +int iruserok(u_long, int, char *, char *); +int isatty(int); +int killpg(int, int); +int listen(int, int); +#ifdef __STDC__ +struct utmp; +#endif +void login(struct utmp *); +int logout(const char *); +off_t lseek(int, off_t, int); +int lstat(const char *, struct stat *); +int mkstemp(char *); +char *mktemp(char *); +int munmap(caddr_t, int); +void openlog(const char *, int, int); +void perror(const char *); +int printf(const char *, ...); +int puts(const char *); +long random(void); +int readlink(const char *, char *, int); +#ifdef __STDC__ +struct iovec; +#endif +int readv(int, struct iovec *, int); +int recv(int, char *, u_int, int); +int recvfrom(int, char *, u_int, int, struct sockaddr *, int *); +int rename(const char *, const char *); +int rcmd(char **, u_short, char *, char *, char *, int *); +int rresvport(int *); +int send(int, char *, u_int, int); +int sendto(int, char *, u_int, int, struct sockaddr *, int); +int setenv(const char *, const char *, int); +int seteuid(int); +int setpriority(int, int, int); +int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); +int setpgrp(int, int); +void setpwent(void); +int setrlimit(int, struct rlimit *); +void setservent(int); +int setsockopt(int, int, int, char *, int); +int shutdown(int, int); +int sigblock(int); +void (*signal (int, void (*) (int))) (int); +int sigpause(int); +int sigsetmask(int); +#ifdef __STDC__ +struct sigvec; +#endif +int sigvec(int, struct sigvec *, struct sigvec*); +int snprintf(char *, size_t, const char *, ...); +int socket(int, int, int); +int socketpair(int, int, int, int *); +int symlink(const char *, const char *); +void srandom(int); +int sscanf(char *, const char *, ...); +int stat(const char *, struct stat *); +int statfs(char *, struct statfs *); +char *strerror(int); +int strcasecmp(const char *, const char *); +#ifdef __STDC__ +struct tm; +#endif +int strftime(char *, int, char *, struct tm *); +int strncasecmp(const char *, const char *, int); +long strtol(const char *, char **, int); +void sync(void); +void syslog(int, const char *, ...); +int system(const char *); +long tell(int); +time_t time(time_t *); +char *timezone(int, int); +int tolower(int); +int toupper(int); +int truncate(char *, off_t); +void unsetenv(const char *); +int vfork(void); +int vsprintf(char *, const char *, ...); +int writev(int, struct iovec *, int); +#ifdef __STDC__ +struct rusage; +#endif +int utimes(const char *, struct timeval *); +#if __GNUC__ <= 1 +int wait(int *); +pid_t wait3(int *, int, struct rusage *); +#endif + +/* Ugly signal hacking */ +#ifdef SIG_ERR +#undef SIG_ERR +#define SIG_ERR (void (*)(int))-1 +#undef SIG_DFL +#define SIG_DFL (void (*)(int))0 +#undef SIG_IGN +#define SIG_IGN (void (*)(int))1 + +#ifdef KERNEL +#undef SIG_CATCH +#define SIG_CATCH (void (*)(int))2 +#endif +#undef SIG_HOLD +#define SIG_HOLD (void (*)(int))3 +#endif diff --git a/tcpdump.tproj/os-ultrix4.h b/tcpdump.tproj/os-ultrix4.h new file mode 100644 index 0000000..623d80a --- /dev/null +++ b/tcpdump.tproj/os-ultrix4.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/os-ultrix4.h,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL) + */ + +/* Prototypes missing in Ultrix 4 */ +int bcmp(const char *, const char *, u_int); +void bcopy(const void *, void *, u_int); +void bzero(void *, u_int); +void endservent(void); +int getopt(int, char * const *, const char *); +#ifdef __STDC__ +struct timeval; +struct timezone; +#endif +int gettimeofday(struct timeval *, struct timezone *); +int ioctl(int, int, caddr_t); +int pfopen(char *, int); +int setlinebuf(FILE *); +int socket(int, int, int); +int strcasecmp(const char *, const char *); diff --git a/tcpdump.tproj/ospf.h b/tcpdump.tproj/ospf.h new file mode 100644 index 0000000..9be2236 --- /dev/null +++ b/tcpdump.tproj/ospf.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) + */ +#define OSPF_TYPE_UMD 0 /* UMd's special monitoring packets */ +#define OSPF_TYPE_HELLO 1 /* Hello */ +#define OSPF_TYPE_DB 2 /* Database Description */ +#define OSPF_TYPE_LSR 3 /* Link State Request */ +#define OSPF_TYPE_LSU 4 /* Link State Update */ +#define OSPF_TYPE_LSA 5 /* Link State Ack */ +#define OSPF_TYPE_MAX 6 + +/* Options *_options */ +#define OSPF_OPTION_T 0x01 /* T bit: TOS support */ +#define OSPF_OPTION_E 0x02 /* E bit: External routes advertised */ +#define OSPF_OPTION_MC 0x04 /* MC bit: Multicast capable */ + +/* ospf_authtype */ +#define OSPF_AUTH_NONE 0 /* No auth-data */ +#define OSPF_AUTH_SIMPLE 1 /* Simple password */ + +/* db_flags */ +#define OSPF_DB_INIT 0x04 /* */ +#define OSPF_DB_MORE 0x02 +#define OSPF_DB_MASTER 0x01 + +/* ls_type */ +#define LS_TYPE_ROUTER 1 /* router link */ +#define LS_TYPE_NETWORK 2 /* network link */ +#define LS_TYPE_SUM_IP 3 /* summary link */ +#define LS_TYPE_SUM_ABR 4 /* summary area link */ +#define LS_TYPE_ASE 5 /* ASE */ +#define LS_TYPE_GROUP 6 /* Group membership (multicast */ + /* extensions 23 July 1991) */ +#define LS_TYPE_MAX 7 + +/************************************************* + * + * is the above a bug in the documentation? + * + *************************************************/ + + +/* rla_link.link_type */ +#define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ +#define RLA_TYPE_TRANSIT 2 /* connection to transit network */ +#define RLA_TYPE_STUB 3 /* connection to stub network */ +#define RLA_TYPE_VIRTUAL 4 /* virtual link */ + +/* rla_flags */ +#define RLA_FLAG_B 0x01 +#define RLA_FLAG_E 0x02 +#define RLA_FLAG_W1 0x04 +#define RLA_FLAG_W2 0x08 + +/* sla_tosmetric breakdown */ +#define SLA_MASK_TOS 0x7f000000 +#define SLA_MASK_METRIC 0x00ffffff +#define SLA_SHIFT_TOS 24 + +/* asla_tosmetric breakdown */ +#define ASLA_FLAG_EXTERNAL 0x80000000 +#define ASLA_MASK_TOS 0x7f000000 +#define ASLA_SHIFT_TOS 24 +#define ASLA_MASK_METRIC 0x00ffffff + +/* multicast vertex type */ +#define MCLA_VERTEX_ROUTER 1 +#define MCLA_VERTEX_NETWORK 2 + +/* link state advertisement header */ +struct lsa_hdr { + u_short ls_age; + u_char ls_options; + u_char ls_type; + struct in_addr ls_stateid; + struct in_addr ls_router; + u_int32_t ls_seq; + u_short ls_chksum; + u_short ls_length; +} ; + +/* link state advertisement */ +struct lsa { + struct lsa_hdr ls_hdr; + + /* Link state types */ + union { + /* Router links advertisements */ + struct { + u_char rla_flags; + u_char rla_zero[1]; + u_short rla_count; + struct rlalink { + struct in_addr link_id; + struct in_addr link_data; + u_char link_type; + u_char link_toscount; + u_short link_tos0metric; + } rla_link[1]; /* may repeat */ + } un_rla; + + /* Network links advertisements */ + struct { + struct in_addr nla_mask; + struct in_addr nla_router[1]; /* may repeat */ + } un_nla; + + /* Summary links advertisements */ + struct { + struct in_addr sla_mask; + u_int32_t sla_tosmetric[1]; /* may repeat */ + } un_sla; + + /* AS external links advertisements */ + struct { + struct in_addr asla_mask; + struct aslametric { + u_int32_t asla_tosmetric; + struct in_addr asla_forward; + struct in_addr asla_tag; + } asla_metric[1]; /* may repeat */ + } un_asla; + + /* Multicast group membership */ + struct mcla { + u_int32_t mcla_vtype; + struct in_addr mcla_vid; + } un_mcla[1]; + } lsa_un; +} ; + + +/* + * TOS metric struct (will be 0 or more in router links update) + */ +struct tos_metric { + u_char tos_type; + u_char tos_zero; + u_short tos_metric; +} ; + +#define OSPF_AUTH_SIZE 8 + +/* + * the main header + */ +struct ospfhdr { + u_char ospf_version; + u_char ospf_type; + u_short ospf_len; + struct in_addr ospf_routerid; + struct in_addr ospf_areaid; + u_short ospf_chksum; + u_short ospf_authtype; + u_char ospf_authdata[OSPF_AUTH_SIZE]; + union { + + /* Hello packet */ + struct { + struct in_addr hello_mask; + u_short hello_helloint; + u_char hello_options; + u_char hello_priority; + u_int32_t hello_deadint; + struct in_addr hello_dr; + struct in_addr hello_bdr; + struct in_addr hello_neighbor[1]; /* may repeat */ + } un_hello; + + /* Database Description packet */ + struct { + u_char db_zero[2]; + u_char db_options; + u_char db_flags; + u_int32_t db_seq; + struct lsa_hdr db_lshdr[1]; /* may repeat */ + } un_db; + + /* Link State Request */ + struct lsr { + u_int32_t ls_type; + struct in_addr ls_stateid; + struct in_addr ls_router; + } un_lsr[1]; /* may repeat */ + + /* Link State Update */ + struct { + u_int32_t lsu_count; + struct lsa lsu_lsa[1]; /* may repeat */ + } un_lsu; + + /* Link State Acknowledgement */ + struct { + struct lsa_hdr lsa_lshdr[1]; /* may repeat */ + } un_lsa ; + } ospf_un ; +} ; + +#define ospf_hello ospf_un.un_hello +#define ospf_db ospf_un.un_db +#define ospf_lsr ospf_un.un_lsr +#define ospf_lsu ospf_un.un_lsu +#define ospf_lsa ospf_un.un_lsa + diff --git a/tcpdump.tproj/parsenfsfh.c b/tcpdump.tproj/parsenfsfh.c new file mode 100644 index 0000000..bdfdf43 --- /dev/null +++ b/tcpdump.tproj/parsenfsfh.c @@ -0,0 +1,443 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * parsenfsfh.c - portable parser for NFS file handles + * uses all sorts of heuristics + * + * Jeffrey C. Mogul + * Digital Equipment Corporation + * Western Research Laboratory + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/parsenfsfh.c,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include +#include +#include + +#include "interface.h" +#include "nfsfh.h" + +/* + * This routine attempts to parse a file handle (in network byte order), + * using heuristics to guess what kind of format it is in. See the + * file "fhandle_layouts" for a detailed description of the various + * patterns we know about. + * + * The file handle is parsed into our internal representation of a + * file-system id, and an internal representation of an inode-number. + */ + +#define FHT_UNKNOWN 0 +#define FHT_AUSPEX 1 +#define FHT_DECOSF 2 +#define FHT_IRIX4 3 +#define FHT_IRIX5 4 +#define FHT_SUNOS3 5 +#define FHT_SUNOS4 6 +#define FHT_ULTRIX 7 +#define FHT_VMSUCX 8 +#define FHT_SUNOS5 9 +#define FHT_AIX32 10 +#define FHT_HPUX9 11 + +#ifdef ultrix +/* Nasty hack to keep the Ultrix C compiler from emitting bogus warnings */ +#define XFF(x) ((u_int32_t)(x)) +#else +#define XFF(x) (x) +#endif + +#define make_uint32(msb,b,c,lsb)\ + (XFF(lsb) + (XFF(c)<<8) + (XFF(b)<<16) + (XFF(msb)<<24)) + +#define make_uint24(msb,b, lsb)\ + (XFF(lsb) + (XFF(b)<<8) + (XFF(msb)<<16)) + +#define make_uint16(msb,lsb)\ + (XFF(lsb) + (XFF(msb)<<8)) + +#ifdef __alpha + /* or other 64-bit systems */ +#define make_uint48(msb,b,c,d,e,lsb)\ + ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24) + ((b)<<32) + ((msb)<<40)) +#else + /* on 32-bit systems ignore high-order bits */ +#define make_uint48(msb,b,c,d,e,lsb)\ + ((lsb) + ((e)<<8) + ((d)<<16) + ((c)<<24)) +#endif + +static int is_UCX(unsigned char *); + +void +Parse_fh(fh, fsidp, inop, osnamep, fsnamep, ourself) +register caddr_t *fh; +my_fsid *fsidp; +ino_t *inop; +char **osnamep; /* if non-NULL, return OS name here */ +char **fsnamep; /* if non-NULL, return server fs name here (for VMS) */ +int ourself; /* true if file handle was generated on this host */ +{ + register unsigned char *fhp = (unsigned char *)fh; + u_int32_t temp; + int fhtype = FHT_UNKNOWN; + + if (ourself) { + /* File handle generated on this host, no need for guessing */ +#if defined(IRIX40) + fhtype = FHT_IRIX4; +#endif +#if defined(IRIX50) + fhtype = FHT_IRIX5; +#endif +#if defined(IRIX51) + fhtype = FHT_IRIX5; +#endif +#if defined(SUNOS4) + fhtype = FHT_SUNOS4; +#endif +#if defined(SUNOS5) + fhtype = FHT_SUNOS5; +#endif +#if defined(ultrix) + fhtype = FHT_ULTRIX; +#endif +#if defined(__osf__) + fhtype = FHT_DECOSF; +#endif + } + /* + * This is basically a big decision tree + */ + else if ((fhp[0] == 0) && (fhp[1] == 0)) { + /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */ + /* probably rules out HP-UX, AIX unless they allow major=0 */ + if ((fhp[2] == 0) && (fhp[3] == 0)) { + /* bytes[2,3] == (0,0); must be Auspex */ + /* XXX or could be Ultrix+MASSBUS "hp" disk? */ + fhtype = FHT_AUSPEX; + } + else { + /* + * bytes[2,3] != (0,0); rules out Auspex, could be + * DECOSF, SUNOS4, or IRIX4 + */ + if ((fhp[4] != 0) && (fhp[5] == 0) && + (fhp[8] == 12) && (fhp[9] == 0)) { + /* seems to be DECOSF, with minor == 0 */ + fhtype = FHT_DECOSF; + } + else { + /* could be SUNOS4 or IRIX4 */ + /* XXX the test of fhp[5] == 8 could be wrong */ + if ((fhp[4] == 0) && (fhp[5] == 8) && (fhp[6] == 0) && + (fhp[7] == 0)) { + /* looks like a length, not a file system typecode */ + fhtype = FHT_IRIX4; + } + else { + /* by elimination */ + fhtype = FHT_SUNOS4; + } + } + } + } + else { + /* + * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4 + * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5 + * could be AIX, HP-UX + */ + if ((fhp[2] == 0) && (fhp[3] == 0)) { + /* + * bytes[2,3] == (0,0); rules out OSF, probably not UCX + * (unless the exported device name is just one letter!), + * could be Ultrix, IRIX5, AIX, or SUNOS5 + * might be HP-UX (depends on their values for minor devs) + */ + /*XXX we probably only need to test of these two bytes */ + if ((fhp[21] == 0) && (fhp[23] == 0)) { + fhtype = FHT_ULTRIX; + } + else { + /* Could be SUNOS5/IRIX5, maybe AIX */ + /* XXX no obvious difference between SUNOS5 and IRIX5 */ + if (fhp[9] == 10) + fhtype = FHT_SUNOS5; + /* XXX what about AIX? */ + } + } + else { + /* + * bytes[2,3] != (0,0); rules out Ultrix, could be + * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX + */ + if ((fhp[8] == 12) && (fhp[9] == 0)) { + fhtype = FHT_DECOSF; + } + else if ((fhp[8] == 0) && (fhp[9] == 10)) { + /* could be SUNOS5/IRIX5, AIX, HP-UX */ + if ((fhp[7] == 0) && (fhp[6] == 0) && + (fhp[5] == 0) && (fhp[4] == 0)) { + /* XXX is this always true of HP-UX? */ + fhtype = FHT_HPUX9; + } + else if (fhp[7] == 2) { + /* This would be MNT_NFS on AIX, which is impossible */ + fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ + } + else { + /* + * XXX Could be SUNOS5/IRIX5 or AIX. I don't + * XXX see any way to disambiguate these, so + * XXX I'm going with the more likely guess. + * XXX Sorry, Big Blue. + */ + fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ + } + } + else { + if (is_UCX(fhp)) { + fhtype = FHT_VMSUCX; + } + else { + fhtype = FHT_UNKNOWN; + } + } + } + } + + /* XXX still needs to handle SUNOS3 */ + + switch (fhtype) { + case FHT_AUSPEX: + fsidp->Fsid_dev.Minor = fhp[7]; + fsidp->Fsid_dev.Major = fhp[6]; + fsidp->fsid_code = 0; + + temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); + *inop = temp; + + if (osnamep) + *osnamep = "Auspex"; + break; + + case FHT_DECOSF: + fsidp->fsid_code = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); + /* XXX could ignore 3 high-order bytes */ + + temp = make_uint32(fhp[3], fhp[2], fhp[1], fhp[0]); + fsidp->Fsid_dev.Minor = temp & 0xFFFFF; + fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF; + + temp = make_uint32(fhp[15], fhp[14], fhp[13], fhp[12]); + *inop = temp; + if (osnamep) + *osnamep = "OSF"; + break; + + case FHT_IRIX4: + fsidp->Fsid_dev.Minor = fhp[3]; + fsidp->Fsid_dev.Major = fhp[2]; + fsidp->fsid_code = 0; + + temp = make_uint32(fhp[8], fhp[9], fhp[10], fhp[11]); + *inop = temp; + + if (osnamep) + *osnamep = "IRIX4"; + break; + + case FHT_IRIX5: + fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); + fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); + fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); + + temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); + *inop = temp; + + if (osnamep) + *osnamep = "IRIX5"; + break; + + case FHT_SUNOS3: + if (osnamep) + *osnamep = "SUNOS3"; + break; + + case FHT_SUNOS4: + fsidp->Fsid_dev.Minor = fhp[3]; + fsidp->Fsid_dev.Major = fhp[2]; + fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); + + temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); + *inop = temp; + + if (osnamep) + *osnamep = "SUNOS4"; + break; + + case FHT_SUNOS5: + temp = make_uint16(fhp[0], fhp[1]); + fsidp->Fsid_dev.Major = (temp>>2) & 0x3FFF; + temp = make_uint24(fhp[1], fhp[2], fhp[3]); + fsidp->Fsid_dev.Minor = temp & 0x3FFFF; + fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); + + temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); + *inop = temp; + + if (osnamep) + *osnamep = "SUNOS5"; + break; + + case FHT_ULTRIX: + fsidp->fsid_code = 0; + fsidp->Fsid_dev.Minor = fhp[0]; + fsidp->Fsid_dev.Major = fhp[1]; + + temp = make_uint32(fhp[7], fhp[6], fhp[5], fhp[4]); + *inop = temp; + if (osnamep) + *osnamep = "Ultrix"; + break; + + case FHT_VMSUCX: + /* No numeric file system ID, so hash on the device-name */ + if (sizeof(*fsidp) >= 14) { + if (sizeof(*fsidp) > 14) + memset((char *)fsidp, 0, sizeof(*fsidp)); + memcpy((char *)fsidp, fh, 14); /* just use the whole thing */ + } + else { + u_int32_t tempa[4]; /* at least 16 bytes, maybe more */ + + memset((char *)tempa, 0, sizeof(tempa)); + memcpy((char *)tempa, fh, 14); /* ensure alignment */ + fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1); + fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1); + fsidp->fsid_code = 0; + } + + /* VMS file ID is: (RVN, FidHi, FidLo) */ + *inop = make_uint32(fhp[26], fhp[27], fhp[23], fhp[22]); + + /* Caller must save (and null-terminate?) this value */ + if (fsnamep) + *fsnamep = (char *)&(fhp[1]); + + if (osnamep) + *osnamep = "VMS"; + break; + + case FHT_AIX32: + fsidp->Fsid_dev.Minor = make_uint16(fhp[2], fhp[3]); + fsidp->Fsid_dev.Major = make_uint16(fhp[0], fhp[1]); + fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); + + temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); + *inop = temp; + + if (osnamep) + *osnamep = "AIX32"; + break; + + case FHT_HPUX9: + fsidp->Fsid_dev.Major = fhp[0]; + temp = make_uint24(fhp[1], fhp[2], fhp[3]); + fsidp->Fsid_dev.Minor = temp; + fsidp->fsid_code = make_uint32(fhp[4], fhp[5], fhp[6], fhp[7]); + + temp = make_uint32(fhp[12], fhp[13], fhp[14], fhp[15]); + *inop = temp; + + if (osnamep) + *osnamep = "HPUX9"; + break; + + case FHT_UNKNOWN: +#ifdef DEBUG + { + /* XXX debugging */ + int i; + for (i = 0; i < 32; i++) + (void)fprintf(stderr, "%x.", fhp[i]); + (void)fprintf(stderr, "\n"); + } +#endif + /* XXX for now, give "bogus" values to aid debugging */ + fsidp->fsid_code = 0; + fsidp->Fsid_dev.Minor = 257; + fsidp->Fsid_dev.Major = 257; + *inop = 1; + + /* display will show this string instead of (257,257) */ + if (fsnamep) + *fsnamep = "Unknown"; + + if (osnamep) + *osnamep = "Unknown"; + break; + + } +} + +/* + * Is this a VMS UCX file handle? + * Check for: + * (1) leading code byte [XXX not yet] + * (2) followed by string of printing chars & spaces + * (3) followed by string of nulls + */ +static int +is_UCX(fhp) +unsigned char *fhp; +{ + register int i; + int seen_null = 0; + + for (i = 1; i < 14; i++) { + if (isprint(fhp[i])) { + if (seen_null) + return(0); + else + continue; + } + else if (fhp[i] == 0) { + seen_null = 1; + continue; + } + else + return(0); + } + + return(1); +} diff --git a/tcpdump.tproj/print-arp.c b/tcpdump.tproj/print-arp.c new file mode 100644 index 0000000..0fe851b --- /dev/null +++ b/tcpdump.tproj/print-arp.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-arp.c,v 1.1.1.1 1999/05/02 03:58:32 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include + +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ethertype.h" +#include "extract.h" /* must come after interface.h */ + +/* Compatibility */ +#ifndef REVARP_REQUEST +#define REVARP_REQUEST 3 +#endif +#ifndef REVARP_REPLY +#define REVARP_REPLY 4 +#endif + +static u_char ezero[6]; + +void +arp_print(register const u_char *bp, u_int length, u_int caplen) +{ + register const struct ether_arp *ap; + register const struct ether_header *eh; + register u_short pro, hrd, op; + + ap = (struct ether_arp *)bp; + if ((u_char *)(ap + 1) > snapend) { + printf("[|arp]"); + return; + } + if (length < sizeof(struct ether_arp)) { + (void)printf("truncated-arp"); + default_print((u_char *)ap, length); + return; + } + + pro = EXTRACT_16BITS(&ap->arp_pro); + hrd = EXTRACT_16BITS(&ap->arp_hrd); + op = EXTRACT_16BITS(&ap->arp_op); + + if ((pro != ETHERTYPE_IP && pro != ETHERTYPE_TRAIL) + || ap->arp_hln != sizeof(SHA(ap)) + || ap->arp_pln != sizeof(SPA(ap))) { + (void)printf("arp-#%d for proto #%d (%d) hardware #%d (%d)", + op, pro, ap->arp_pln, + hrd, ap->arp_hln); + return; + } + if (pro == ETHERTYPE_TRAIL) + (void)printf("trailer-"); + eh = (struct ether_header *)packetp; + switch (op) { + + case ARPOP_REQUEST: + (void)printf("arp who-has %s", ipaddr_string(TPA(ap))); + if (memcmp((char *)ezero, (char *)THA(ap), 6) != 0) + (void)printf(" (%s)", etheraddr_string(THA(ap))); + (void)printf(" tell %s", ipaddr_string(SPA(ap))); + if (memcmp((char *)ESRC(eh), (char *)SHA(ap), 6) != 0) + (void)printf(" (%s)", etheraddr_string(SHA(ap))); + break; + + case ARPOP_REPLY: + (void)printf("arp reply %s", ipaddr_string(SPA(ap))); + if (memcmp((char *)ESRC(eh), (char *)SHA(ap), 6) != 0) + (void)printf(" (%s)", etheraddr_string(SHA(ap))); + (void)printf(" is-at %s", etheraddr_string(SHA(ap))); + if (memcmp((char *)EDST(eh), (char *)THA(ap), 6) != 0) + (void)printf(" (%s)", etheraddr_string(THA(ap))); + break; + + case REVARP_REQUEST: + (void)printf("rarp who-is %s tell %s", + etheraddr_string(THA(ap)), + etheraddr_string(SHA(ap))); + break; + + case REVARP_REPLY: + (void)printf("rarp reply %s at %s", + etheraddr_string(THA(ap)), + ipaddr_string(TPA(ap))); + break; + + default: + (void)printf("arp-#%d", op); + default_print((u_char *)ap, caplen); + return; + } + if (hrd != ARPHRD_ETHER) + printf(" hardware #%d", hrd); +} diff --git a/tcpdump.tproj/print-atalk.c b/tcpdump.tproj/print-atalk.c new file mode 100644 index 0000000..f939466 --- /dev/null +++ b/tcpdump.tproj/print-atalk.c @@ -0,0 +1,595 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print AppleTalk packets. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-atalk.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ethertype.h" +#include "extract.h" /* must come after interface.h */ +#include "appletalk.h" + +static struct tok type2str[] = { + { ddpRTMP, "rtmp" }, + { ddpRTMPrequest, "rtmpReq" }, + { ddpECHO, "echo" }, + { ddpIP, "IP" }, + { ddpARP, "ARP" }, + { ddpKLAP, "KLAP" }, + { 0, NULL } +}; + +struct aarp { + u_short htype, ptype; + u_char halen, palen; + u_short op; + u_char hsaddr[6]; + u_char psaddr[4]; + u_char hdaddr[6]; + u_char pdaddr[4]; +}; + +static char tstr[] = "[|atalk]"; + +static void atp_print(const struct atATP *, u_int); +static void atp_bitmap_print(u_char); +static void nbp_print(const struct atNBP *, u_int, u_short, u_char, u_char); +static const char *print_cstring(const char *, const u_char *); +static const struct atNBPtuple *nbp_tuple_print(const struct atNBPtuple *, + const u_char *, + u_short, u_char, u_char); +static const struct atNBPtuple *nbp_name_print(const struct atNBPtuple *, + const u_char *); +static const char *ataddr_string(u_short, u_char); +static void ddp_print(const u_char *, u_int, int, u_short, u_char, u_char); +static const char *ddpskt_string(int); + +/* + * Print AppleTalk Datagram Delivery Protocol packets. + */ +void +atalk_print(register const u_char *bp, u_int length) +{ + register const struct LAP *lp; + register const struct atDDP *dp; + register const struct atShortDDP *sdp; + u_short snet; + + lp = (struct LAP *)bp; + bp += sizeof(*lp); + length -= sizeof(*lp); + switch (lp->type) { + + case lapShortDDP: + if (length < ddpSSize) { + (void)printf(" [|sddp %d]", length); + return; + } + sdp = (const struct atShortDDP *)bp; + printf("%s.%s", + ataddr_string(0, lp->src), ddpskt_string(sdp->srcSkt)); + printf(" > %s.%s:", + ataddr_string(0, lp->dst), ddpskt_string(sdp->dstSkt)); + bp += ddpSSize; + length -= ddpSSize; + ddp_print(bp, length, sdp->type, 0, lp->src, sdp->srcSkt); + break; + + case lapDDP: + if (length < ddpSize) { + (void)printf(" [|ddp %d]", length); + return; + } + dp = (const struct atDDP *)bp; + snet = EXTRACT_16BITS(&dp->srcNet); + printf("%s.%s", ataddr_string(snet, dp->srcNode), + ddpskt_string(dp->srcSkt)); + printf(" > %s.%s:", + ataddr_string(EXTRACT_16BITS(&dp->dstNet), dp->dstNode), + ddpskt_string(dp->dstSkt)); + bp += ddpSize; + length -= ddpSize; + ddp_print(bp, length, dp->type, snet, dp->srcNode, dp->srcSkt); + break; + +#ifdef notdef + case lapKLAP: + klap_print(bp, length); + break; +#endif + + default: + printf("%d > %d at-lap#%d %d", + lp->src, lp->dst, lp->type, length); + break; + } +} + +/* XXX should probably pass in the snap header and do checks like arp_print() */ +void +aarp_print(register const u_char *bp, u_int length) +{ + register const struct aarp *ap; + +#define AT(member) ataddr_string((ap->member[1]<<8)|ap->member[2],ap->member[3]) + + printf("aarp "); + ap = (const struct aarp *)bp; + if (ap->htype == 1 && ap->ptype == ETHERTYPE_ATALK && + ap->halen == 6 && ap->palen == 4 ) + switch (ap->op) { + + case 1: /* request */ + (void)printf("who-has %s tell %s", + AT(pdaddr), AT(psaddr)); + return; + + case 2: /* response */ + (void)printf("reply %s is-at %s", + AT(pdaddr), etheraddr_string(ap->hdaddr)); + return; + + case 3: /* probe (oy!) */ + (void)printf("probe %s tell %s", + AT(pdaddr), AT(psaddr)); + return; + } + (void)printf("len %d op %d htype %d ptype %#x halen %d palen %d", + length, ap->op, ap->htype, ap->ptype, ap->halen, ap->palen ); +} + +static void +ddp_print(register const u_char *bp, register u_int length, register int t, + register u_short snet, register u_char snode, u_char skt) +{ + + switch (t) { + + case ddpNBP: + nbp_print((const struct atNBP *)bp, length, snet, snode, skt); + break; + + case ddpATP: + atp_print((const struct atATP *)bp, length); + break; + + default: + (void)printf(" at-%s %d", tok2str(type2str, NULL, t), length); + break; + } +} + +static void +atp_print(register const struct atATP *ap, u_int length) +{ + char c; + u_int32_t data; + + if ((const u_char *)(ap + 1) > snapend) { + /* Just bail if we don't have the whole chunk. */ + fputs(tstr, stdout); + return; + } + length -= sizeof(*ap); + switch (ap->control & 0xc0) { + + case atpReqCode: + (void)printf(" atp-req%s %d", + ap->control & atpXO? " " : "*", + EXTRACT_16BITS(&ap->transID)); + + atp_bitmap_print(ap->bitmap); + + if (length != 0) + (void)printf(" [len=%d]", length); + + switch (ap->control & (atpEOM|atpSTS)) { + case atpEOM: + (void)printf(" [EOM]"); + break; + case atpSTS: + (void)printf(" [STS]"); + break; + case atpEOM|atpSTS: + (void)printf(" [EOM,STS]"); + break; + } + break; + + case atpRspCode: + (void)printf(" atp-resp%s%d:%d (%d)", + ap->control & atpEOM? "*" : " ", + EXTRACT_16BITS(&ap->transID), ap->bitmap, length); + switch (ap->control & (atpXO|atpSTS)) { + case atpXO: + (void)printf(" [XO]"); + break; + case atpSTS: + (void)printf(" [STS]"); + break; + case atpXO|atpSTS: + (void)printf(" [XO,STS]"); + break; + } + break; + + case atpRelCode: + (void)printf(" atp-rel %d", EXTRACT_16BITS(&ap->transID)); + + atp_bitmap_print(ap->bitmap); + + /* length should be zero */ + if (length) + (void)printf(" [len=%d]", length); + + /* there shouldn't be any control flags */ + if (ap->control & (atpXO|atpEOM|atpSTS)) { + c = '['; + if (ap->control & atpXO) { + (void)printf("%cXO", c); + c = ','; + } + if (ap->control & atpEOM) { + (void)printf("%cEOM", c); + c = ','; + } + if (ap->control & atpSTS) { + (void)printf("%cSTS", c); + c = ','; + } + (void)printf("]"); + } + break; + + default: + (void)printf(" atp-0x%x %d (%d)", ap->control, + EXTRACT_16BITS(&ap->transID), length); + break; + } + data = EXTRACT_32BITS(&ap->userData); + if (data != 0) + (void)printf(" 0x%x", data); +} + +static void +atp_bitmap_print(register u_char bm) +{ + register char c; + register int i; + + /* + * The '& 0xff' below is needed for compilers that want to sign + * extend a u_char, which is the case with the Ultrix compiler. + * (gcc is smart enough to eliminate it, at least on the Sparc). + */ + if ((bm + 1) & (bm & 0xff)) { + c = '<'; + for (i = 0; bm; ++i) { + if (bm & 1) { + (void)printf("%c%d", c, i); + c = ','; + } + bm >>= 1; + } + (void)printf(">"); + } else { + for (i = 0; bm; ++i) + bm >>= 1; + if (i > 1) + (void)printf("<0-%d>", i - 1); + else + (void)printf("<0>"); + } +} + +static void +nbp_print(register const struct atNBP *np, u_int length, register u_short snet, + register u_char snode, register u_char skt) +{ + register const struct atNBPtuple *tp = + (struct atNBPtuple *)((u_char *)np + nbpHeaderSize); + int i; + const u_char *ep; + + length -= nbpHeaderSize; + if (length < 8) { + /* must be room for at least one tuple */ + (void)printf(" truncated-nbp %d", length + nbpHeaderSize); + return; + } + /* ep points to end of available data */ + ep = snapend; + if ((const u_char *)tp > ep) { + fputs(tstr, stdout); + return; + } + switch (i = np->control & 0xf0) { + + case nbpBrRq: + case nbpLkUp: + (void)printf(i == nbpLkUp? " nbp-lkup %d:":" nbp-brRq %d:", + np->id); + if ((const u_char *)(tp + 1) > ep) { + fputs(tstr, stdout); + return; + } + (void)nbp_name_print(tp, ep); + /* + * look for anomalies: the spec says there can only + * be one tuple, the address must match the source + * address and the enumerator should be zero. + */ + if ((np->control & 0xf) != 1) + (void)printf(" [ntup=%d]", np->control & 0xf); + if (tp->enumerator) + (void)printf(" [enum=%d]", tp->enumerator); + if (EXTRACT_16BITS(&tp->net) != snet || + tp->node != snode || tp->skt != skt) + (void)printf(" [addr=%s.%d]", + ataddr_string(EXTRACT_16BITS(&tp->net), + tp->node), tp->skt); + break; + + case nbpLkUpReply: + (void)printf(" nbp-reply %d:", np->id); + + /* print each of the tuples in the reply */ + for (i = np->control & 0xf; --i >= 0 && tp; ) + tp = nbp_tuple_print(tp, ep, snet, snode, skt); + break; + + default: + (void)printf(" nbp-0x%x %d (%d)", np->control, np->id, + length); + break; + } +} + +/* print a counted string */ +static const char * +print_cstring(register const char *cp, register const u_char *ep) +{ + register u_int length; + + if (cp >= (const char *)ep) { + fputs(tstr, stdout); + return (0); + } + length = *cp++; + + /* Spec says string can be at most 32 bytes long */ + if (length < 0 || length > 32) { + (void)printf("[len=%d]", length); + return (0); + } + while (--length >= 0) { + if (cp >= (char *)ep) { + fputs(tstr, stdout); + return (0); + } + putchar(*cp++); + } + return (cp); +} + +static const struct atNBPtuple * +nbp_tuple_print(register const struct atNBPtuple *tp, + register const u_char *ep, + register u_short snet, register u_char snode, + register u_char skt) +{ + register const struct atNBPtuple *tpn; + + if ((const u_char *)(tp + 1) > ep) { + fputs(tstr, stdout); + return 0; + } + tpn = nbp_name_print(tp, ep); + + /* if the enumerator isn't 1, print it */ + if (tp->enumerator != 1) + (void)printf("(%d)", tp->enumerator); + + /* if the socket doesn't match the src socket, print it */ + if (tp->skt != skt) + (void)printf(" %d", tp->skt); + + /* if the address doesn't match the src address, it's an anomaly */ + if (EXTRACT_16BITS(&tp->net) != snet || tp->node != snode) + (void)printf(" [addr=%s]", + ataddr_string(EXTRACT_16BITS(&tp->net), tp->node)); + + return (tpn); +} + +static const struct atNBPtuple * +nbp_name_print(const struct atNBPtuple *tp, register const u_char *ep) +{ + register const char *cp = (const char *)tp + nbpTupleSize; + + putchar(' '); + + /* Object */ + putchar('"'); + if ((cp = print_cstring(cp, ep)) != NULL) { + /* Type */ + putchar(':'); + if ((cp = print_cstring(cp, ep)) != NULL) { + /* Zone */ + putchar('@'); + if ((cp = print_cstring(cp, ep)) != NULL) + putchar('"'); + } + } + return ((const struct atNBPtuple *)cp); +} + + +#define HASHNAMESIZE 4096 + +struct hnamemem { + int addr; + char *name; + struct hnamemem *nxt; +}; + +static struct hnamemem hnametable[HASHNAMESIZE]; + +static const char * +ataddr_string(u_short atnet, u_char athost) +{ + register struct hnamemem *tp, *tp2; + register int i = (atnet << 8) | athost; + char nambuf[256]; + static int first = 1; + FILE *fp; + + /* + * if this is the first call, see if there's an AppleTalk + * number to name map file. + */ + if (first && (first = 0, !nflag) + && (fp = fopen("/etc/atalk.names", "r"))) { + char line[256]; + int i1, i2, i3; + + while (fgets(line, sizeof(line), fp)) { + if (line[0] == '\n' || line[0] == 0 || line[0] == '#') + continue; + if (sscanf(line, "%d.%d.%d %s", &i1, &i2, &i3, + nambuf) == 4) + /* got a hostname. */ + i3 |= ((i1 << 8) | i2) << 8; + else if (sscanf(line, "%d.%d %s", &i1, &i2, + nambuf) == 3) + /* got a net name */ + i3 = (((i1 << 8) | i2) << 8) | 255; + else + continue; + + for (tp = &hnametable[i3 & (HASHNAMESIZE-1)]; + tp->nxt; tp = tp->nxt) + ; + tp->addr = i3; + tp->nxt = newhnamemem(); + tp->name = savestr(nambuf); + } + fclose(fp); + } + + for (tp = &hnametable[i & (HASHNAMESIZE-1)]; tp->nxt; tp = tp->nxt) + if (tp->addr == i) + return (tp->name); + + /* didn't have the node name -- see if we've got the net name */ + i |= 255; + for (tp2 = &hnametable[i & (HASHNAMESIZE-1)]; tp2->nxt; tp2 = tp2->nxt) + if (tp2->addr == i) { + tp->addr = (atnet << 8) | athost; + tp->nxt = newhnamemem(); + (void)sprintf(nambuf, "%s.%d", tp2->name, athost); + tp->name = savestr(nambuf); + return (tp->name); + } + + tp->addr = (atnet << 8) | athost; + tp->nxt = newhnamemem(); + if (athost != 255) + (void)sprintf(nambuf, "%d.%d.%d", + atnet >> 8, atnet & 0xff, athost); + else + (void)sprintf(nambuf, "%d.%d", atnet >> 8, atnet & 0xff); + tp->name = savestr(nambuf); + + return (tp->name); +} + +static struct tok skt2str[] = { + { rtmpSkt, "rtmp" }, /* routing table maintenance */ + { nbpSkt, "nis" }, /* name info socket */ + { echoSkt, "echo" }, /* AppleTalk echo protocol */ + { zipSkt, "zip" }, /* zone info protocol */ + { 0, NULL } +}; + +static const char * +ddpskt_string(register int skt) +{ + static char buf[8]; + + if (nflag) { + (void)sprintf(buf, "%d", skt); + return (buf); + } + return (tok2str(skt2str, "%d", skt)); +} diff --git a/tcpdump.tproj/print-atm.c b/tcpdump.tproj/print-atm.c new file mode 100644 index 0000000..4abe2ad --- /dev/null +++ b/tcpdump.tproj/print-atm.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-atm.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "addrtoname.h" +#include "ethertype.h" +#include "interface.h" + +/* + * This is the top level routine of the printer. 'p' is the points + * to the LLC/SNAP header of the packet, 'tvp' is the timestamp, + * 'length' is the length of the packet off the wire, and 'caplen' + * is the number of bytes actually captured. + */ +void +atm_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + u_int caplen = h->caplen; + u_int length = h->len; + u_short ethertype; + + ts_print(&h->ts); + + if (caplen < 8) { + printf("[|atm]"); + goto out; + } + if (p[0] != 0xaa || p[1] != 0xaa || p[2] != 0x03) { + /*XXX assume 802.6 MAC header from fore driver */ + if (eflag) + printf("%04x%04x %04x%04x ", + p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3], + p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7], + p[8] << 24 | p[9] << 16 | p[10] << 8 | p[11], + p[12] << 24 | p[13] << 16 | p[14] << 8 | p[15]); + p += 20; + length -= 20; + caplen -= 20; + } + ethertype = p[6] << 8 | p[7]; + if (eflag) + printf("%02x %02x %02x %02x-%02x-%02x %04x: ", + p[0], p[1], p[2], /* dsap/ssap/ctrl */ + p[3], p[4], p[5], /* manufacturer's code */ + ethertype); + + /* + * Some printers want to get back at the ethernet addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = p; + snapend = p + caplen; + + length -= 8; + caplen -= 8; + p += 8; + + switch (ethertype) { + + case ETHERTYPE_IP: + ip_print(p, length); + break; + + /*XXX this probably isn't right */ + case ETHERTYPE_ARP: + case ETHERTYPE_REVARP: + arp_print(p, length, caplen); + break; +#ifdef notyet + case ETHERTYPE_DN: + decnet_print(p, length, caplen); + break; + + case ETHERTYPE_ATALK: + if (vflag) + fputs("et1 ", stdout); + atalk_print(p, length); + break; + + case ETHERTYPE_AARP: + aarp_print(p, length); + break; + + case ETHERTYPE_LAT: + case ETHERTYPE_MOPRC: + case ETHERTYPE_MOPDL: + /* default_print for now */ +#endif + default: + /* ether_type not known, print raw packet */ + if (!eflag) + printf("%02x %02x %02x %02x-%02x-%02x %04x: ", + p[0], p[1], p[2], /* dsap/ssap/ctrl */ + p[3], p[4], p[5], /* manufacturer's code */ + ethertype); + if (!xflag && !qflag) + default_print(p, caplen); + } + if (xflag) + default_print(p, caplen); + out: + putchar('\n'); +} diff --git a/tcpdump.tproj/print-bootp.c b/tcpdump.tproj/print-bootp.c new file mode 100644 index 0000000..c938728 --- /dev/null +++ b/tcpdump.tproj/print-bootp.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print bootp packets. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-bootp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "bootp.h" + +static void rfc1048_print(const u_char *, u_int); +static void cmu_print(const u_char *, u_int); + +static char tstr[] = " [|bootp]"; + +/* + * Print bootp requests + */ +void +bootp_print(register const u_char *cp, u_int length, + u_short sport, u_short dport) +{ + register const struct bootp *bp; + static u_char vm_cmu[4] = VM_CMU; + static u_char vm_rfc1048[4] = VM_RFC1048; + + bp = (struct bootp *)cp; + TCHECK(bp->bp_op); + switch (bp->bp_op) { + + case BOOTREQUEST: + /* Usually, a request goes from a client to a server */ + if (sport != IPPORT_BOOTPC || dport != IPPORT_BOOTPS) + printf(" (request)"); + break; + + case BOOTREPLY: + /* Usually, a reply goes from a server to a client */ + if (sport != IPPORT_BOOTPS || dport != IPPORT_BOOTPC) + printf(" (reply)"); + break; + + default: + printf(" bootp-#%d", bp->bp_op); + } + + TCHECK(bp->bp_secs); + + /* The usual hardware address type is 1 (10Mb Ethernet) */ + if (bp->bp_htype != 1) + printf(" htype-#%d", bp->bp_htype); + + /* The usual length for 10Mb Ethernet address is 6 bytes */ + if (bp->bp_htype != 1 || bp->bp_hlen != 6) + printf(" hlen:%d", bp->bp_hlen); + + /* Only print interesting fields */ + if (bp->bp_hops) + printf(" hops:%d", bp->bp_hops); + if (bp->bp_xid) + printf(" xid:0x%x", (u_int32_t)ntohl(bp->bp_xid)); + if (bp->bp_secs) + printf(" secs:%d", ntohs(bp->bp_secs)); + + /* Client's ip address */ + TCHECK(bp->bp_ciaddr); + if (bp->bp_ciaddr.s_addr) + printf(" C:%s", ipaddr_string(&bp->bp_ciaddr)); + + /* 'your' ip address (bootp client) */ + TCHECK(bp->bp_yiaddr); + if (bp->bp_yiaddr.s_addr) + printf(" Y:%s", ipaddr_string(&bp->bp_yiaddr)); + + /* Server's ip address */ + TCHECK(bp->bp_siaddr); + if (bp->bp_siaddr.s_addr) + printf(" S:%s", ipaddr_string(&bp->bp_siaddr)); + + /* Gateway's ip address */ + TCHECK(bp->bp_giaddr); + if (bp->bp_giaddr.s_addr) + printf(" G:%s", ipaddr_string(&bp->bp_giaddr)); + + /* Client's Ethernet address */ + if (bp->bp_htype == 1 && bp->bp_hlen == 6) { + register const struct ether_header *eh; + register const char *e; + + TCHECK2(bp->bp_chaddr[0], 6); + eh = (struct ether_header *)packetp; + if (bp->bp_op == BOOTREQUEST) + e = (const char *)ESRC(eh); + else if (bp->bp_op == BOOTREPLY) + e = (const char *)EDST(eh); + else + e = 0; + if (e == 0 || memcmp((char *)bp->bp_chaddr, e, 6) != 0) + printf(" ether %s", etheraddr_string(bp->bp_chaddr)); + } + + TCHECK2(bp->bp_sname[0], 1); /* check first char only */ + if (*bp->bp_sname) { + printf(" sname \""); + if (fn_print(bp->bp_sname, snapend)) { + putchar('"'); + fputs(tstr + 1, stdout); + return; + } + } + TCHECK2(bp->bp_sname[0], 1); /* check first char only */ + if (*bp->bp_file) { + printf(" file \""); + if (fn_print(bp->bp_file, snapend)) { + putchar('"'); + fputs(tstr + 1, stdout); + return; + } + } + + /* Decode the vendor buffer */ + TCHECK(bp->bp_vend[0]); + length -= sizeof(*bp) - sizeof(bp->bp_vend); + if (memcmp((char *)bp->bp_vend, (char *)vm_rfc1048, + sizeof(u_int32_t)) == 0) + rfc1048_print(bp->bp_vend, length); + else if (memcmp((char *)bp->bp_vend, (char *)vm_cmu, + sizeof(u_int32_t)) == 0) + cmu_print(bp->bp_vend, length); + else { + u_int32_t ul; + + memcpy((char *)&ul, (char *)bp->bp_vend, sizeof(ul)); + if (ul != 0) + printf("vend-#0x%x", ul); + } + + return; +trunc: + fputs(tstr, stdout); +} + +/* The first character specifies the format to print */ +static struct tok tag2str[] = { +/* RFC1048 tags */ + { TAG_PAD, " PAD" }, + { TAG_SUBNET_MASK, "iSM" }, /* subnet mask (RFC950) */ + { TAG_TIME_OFFSET, "lTZ" }, /* seconds from UTC */ + { TAG_GATEWAY, "iDG" }, /* default gateway */ + { TAG_TIME_SERVER, "iTS" }, /* time servers (RFC868) */ + { TAG_NAME_SERVER, "iIEN" }, /* IEN name servers (IEN116) */ + { TAG_DOMAIN_SERVER, "iNS" }, /* domain name (RFC1035) */ + { TAG_LOG_SERVER, "iLOG" }, /* MIT log servers */ + { TAG_COOKIE_SERVER, "iCS" }, /* cookie servers (RFC865) */ + { TAG_LPR_SERVER, "iLPR" }, /* lpr server (RFC1179) */ + { TAG_IMPRESS_SERVER, "iIM" }, /* impress servers (Imagen) */ + { TAG_RLP_SERVER, "iRL" }, /* resource location (RFC887) */ + { TAG_HOSTNAME, "aHN" }, /* ascii hostname */ + { TAG_BOOTSIZE, "sBS" }, /* 512 byte blocks */ + { TAG_END, " END" }, +/* RFC1497 tags */ + { TAG_DUMPPATH, "aDP" }, + { TAG_DOMAINNAME, "aDN" }, + { TAG_SWAP_SERVER, "iSS" }, + { TAG_ROOTPATH, "aRP" }, + { TAG_EXTPATH, "aEP" }, + { 0, NULL } +}; + +static void +rfc1048_print(register const u_char *bp, register u_int length) +{ + register u_char tag; + register u_int len, size; + register const char *cp; + register char c; + int first; + u_int32_t ul; + u_short us; + + printf(" vend-rfc1048"); + + /* Step over magic cookie */ + bp += sizeof(int32_t); + + /* Loop while we there is a tag left in the buffer */ + while (bp + 1 < snapend) { + tag = *bp++; + if (tag == TAG_PAD) + continue; + if (tag == TAG_END) + return; + cp = tok2str(tag2str, "?T%d", tag); + c = *cp++; + printf(" %s:", cp); + + /* Get the length; check for truncation */ + if (bp + 1 >= snapend) { + fputs(tstr, stdout); + return; + } + len = *bp++; + if (bp + len >= snapend) { + fputs(tstr, stdout); + return; + } + + /* Print data */ + size = len; + if (c == '?') { + /* Base default formats for unknown tags on data size */ + if (size & 1) + c = 'b'; + else if (size & 2) + c = 's'; + else + c = 'l'; + } + first = 1; + switch (c) { + + case 'a': + /* ascii strings */ + putchar('"'); + (void)fn_printn(bp, size, NULL); + putchar('"'); + bp += size; + size = 0; + break; + + case 'i': + case 'l': + /* ip addresses/32-bit words */ + while (size >= sizeof(ul)) { + if (!first) + putchar(','); + memcpy((char *)&ul, (char *)bp, sizeof(ul)); + if (c == 'i') + printf("%s", ipaddr_string(&ul)); + else + printf("%u", ul); + bp += sizeof(ul); + size -= sizeof(ul); + first = 0; + } + break; + + case 's': + /* shorts */ + while (size >= sizeof(us)) { + if (!first) + putchar(','); + memcpy((char *)&us, (char *)bp, sizeof(us)); + printf("%d", us); + bp += sizeof(us); + size -= sizeof(us); + first = 0; + } + break; + + case 'b': + default: + /* Bytes */ + while (size > 0) { + if (!first) + putchar('.'); + printf("%d", *bp); + ++bp; + --size; + first = 0; + } + break; + } + /* Data left over? */ + if (size) + printf("[len %d]", len); + } +} + +static void +cmu_print(register const u_char *bp, register u_int length) +{ + register const struct cmu_vend *cmu; + char *fmt = " %s:%s"; + +#define PRINTCMUADDR(m, s) { TCHECK(cmu->m); \ + if (cmu->m.s_addr != 0) \ + printf(fmt, s, ipaddr_string(&cmu->m.s_addr)); } + + printf(" vend-cmu"); + cmu = (struct cmu_vend *)bp; + + /* Only print if there are unknown bits */ + TCHECK(cmu->v_flags); + if ((cmu->v_flags & ~(VF_SMASK)) != 0) + printf(" F:0x%x", cmu->v_flags); + PRINTCMUADDR(v_dgate, "DG"); + PRINTCMUADDR(v_smask, cmu->v_flags & VF_SMASK ? "SM" : "SM*"); + PRINTCMUADDR(v_dns1, "NS1"); + PRINTCMUADDR(v_dns2, "NS2"); + PRINTCMUADDR(v_ins1, "IEN1"); + PRINTCMUADDR(v_ins2, "IEN2"); + PRINTCMUADDR(v_ts1, "TS1"); + PRINTCMUADDR(v_ts2, "TS2"); + return; + +trunc: + fputs(tstr, stdout); +#undef PRINTCMUADDR +} diff --git a/tcpdump.tproj/print-decnet.c b/tcpdump.tproj/print-decnet.c new file mode 100644 index 0000000..a65152e --- /dev/null +++ b/tcpdump.tproj/print-decnet.c @@ -0,0 +1,798 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-decnet.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#ifdef HAVE_LIBDNET +#include +#endif + +#include +#include +#include +#include +#include + +#include "decnet.h" +#include "extract.h" +#include "interface.h" +#include "addrtoname.h" + +/* Forwards */ +static void print_decnet_ctlmsg(const union routehdr *, u_int); +static void print_t_info(int); +static void print_l1_routes(const char *, u_int); +static void print_l2_routes(const char *, u_int); +static void print_i_info(int); +static void print_elist(const char *, u_int); +static void print_nsp(const u_char *, u_int); +static void print_reason(int); +#ifdef PRINT_NSPDATA +static void pdata(u_char *, int); +#endif + +#ifdef HAVE_LIBDNET +extern char *dnet_htoa(struct dn_naddr *); +#endif + +void +decnet_print(register const u_char *ap, register u_int length, + register u_int caplen) +{ + static union routehdr rhcopy; + register union routehdr *rhp = &rhcopy; + register int mflags; + int dst, src, hops; + u_int rhlen, nsplen, pktlen; + const u_char *nspp; + + if (length < sizeof(struct shorthdr)) { + (void)printf("[|decnet]"); + return; + } + + pktlen = EXTRACT_LE_16BITS(ap); + + rhlen = min(length, caplen); + rhlen = min(rhlen, sizeof(*rhp)); + memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen); + + mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); + + if (mflags & RMF_PAD) { + /* pad bytes of some sort in front of message */ + u_int padlen = mflags & RMF_PADMASK; + if (vflag) + (void) printf("[pad:%d] ", padlen); + ap += padlen; + length -= padlen; + caplen -= padlen; + rhlen = min(length, caplen); + rhlen = min(rhlen, sizeof(*rhp)); + memcpy((char *)rhp, (char *)&(ap[sizeof(short)]), rhlen); + mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); + } + + if (mflags & RMF_FVER) { + (void) printf("future-version-decnet"); + default_print(ap, length); + return; + } + + /* is it a control message? */ + if (mflags & RMF_CTLMSG) { + print_decnet_ctlmsg(rhp, min(length, caplen)); + return; + } + + switch (mflags & RMF_MASK) { + case RMF_LONG: + dst = + EXTRACT_LE_16BITS(rhp->rh_long.lg_dst.dne_remote.dne_nodeaddr); + src = + EXTRACT_LE_16BITS(rhp->rh_long.lg_src.dne_remote.dne_nodeaddr); + hops = EXTRACT_LE_8BITS(rhp->rh_long.lg_visits); + nspp = &(ap[sizeof(short) + sizeof(struct longhdr)]); + nsplen = min((length - sizeof(struct longhdr)), + (caplen - sizeof(struct longhdr))); + break; + case RMF_SHORT: + dst = EXTRACT_LE_16BITS(rhp->rh_short.sh_dst); + src = EXTRACT_LE_16BITS(rhp->rh_short.sh_src); + hops = (EXTRACT_LE_8BITS(rhp->rh_short.sh_visits) & VIS_MASK)+1; + nspp = &(ap[sizeof(short) + sizeof(struct shorthdr)]); + nsplen = min((length - sizeof(struct shorthdr)), + (caplen - sizeof(struct shorthdr))); + break; + default: + (void) printf("unknown message flags under mask"); + default_print((u_char *)ap, length); + return; + } + + (void)printf("%s > %s %d ", + dnaddr_string(src), dnaddr_string(dst), pktlen); + if (vflag) { + if (mflags & RMF_RQR) + (void)printf("RQR "); + if (mflags & RMF_RTS) + (void)printf("RTS "); + if (mflags & RMF_IE) + (void)printf("IE "); + (void)printf("%d hops ", hops); + } + + print_nsp(nspp, nsplen); +} + +static void +print_decnet_ctlmsg(register const union routehdr *rhp, u_int length) +{ + int mflags = EXTRACT_LE_8BITS(rhp->rh_short.sh_flags); + register union controlmsg *cmp = (union controlmsg *)rhp; + int src, dst, info, blksize, eco, ueco, hello, other, vers; + etheraddr srcea, rtea; + int priority; + char *rhpx = (char *)rhp; + + switch (mflags & RMF_CTLMASK) { + case RMF_INIT: + (void)printf("init "); + src = EXTRACT_LE_16BITS(cmp->cm_init.in_src); + info = EXTRACT_LE_8BITS(cmp->cm_init.in_info); + blksize = EXTRACT_LE_16BITS(cmp->cm_init.in_blksize); + vers = EXTRACT_LE_8BITS(cmp->cm_init.in_vers); + eco = EXTRACT_LE_8BITS(cmp->cm_init.in_eco); + ueco = EXTRACT_LE_8BITS(cmp->cm_init.in_ueco); + hello = EXTRACT_LE_16BITS(cmp->cm_init.in_hello); + print_t_info(info); + (void)printf( + "src %sblksize %d vers %d eco %d ueco %d hello %d", + dnaddr_string(src), blksize, vers, eco, ueco, + hello); + break; + case RMF_VER: + (void)printf("verification "); + src = EXTRACT_LE_16BITS(cmp->cm_ver.ve_src); + other = EXTRACT_LE_8BITS(cmp->cm_ver.ve_fcnval); + (void)printf("src %s fcnval %o", dnaddr_string(src), other); + break; + case RMF_TEST: + (void)printf("test "); + src = EXTRACT_LE_16BITS(cmp->cm_test.te_src); + other = EXTRACT_LE_8BITS(cmp->cm_test.te_data); + (void)printf("src %s data %o", dnaddr_string(src), other); + break; + case RMF_L1ROUT: + (void)printf("lev-1-routing "); + src = EXTRACT_LE_16BITS(cmp->cm_l1rou.r1_src); + (void)printf("src %s ", dnaddr_string(src)); + print_l1_routes(&(rhpx[sizeof(struct l1rout)]), + length - sizeof(struct l1rout)); + break; + case RMF_L2ROUT: + (void)printf("lev-2-routing "); + src = EXTRACT_LE_16BITS(cmp->cm_l2rout.r2_src); + (void)printf("src %s ", dnaddr_string(src)); + print_l2_routes(&(rhpx[sizeof(struct l2rout)]), + length - sizeof(struct l2rout)); + break; + case RMF_RHELLO: + (void)printf("router-hello "); + vers = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_vers); + eco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_eco); + ueco = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_ueco); + memcpy((char *)&srcea, (char *)&(cmp->cm_rhello.rh_src), + sizeof(srcea)); + src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); + info = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_info); + blksize = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_blksize); + priority = EXTRACT_LE_8BITS(cmp->cm_rhello.rh_priority); + hello = EXTRACT_LE_16BITS(cmp->cm_rhello.rh_hello); + print_i_info(info); + (void)printf( + "vers %d eco %d ueco %d src %s blksize %d pri %d hello %d", + vers, eco, ueco, dnaddr_string(src), + blksize, priority, hello); + print_elist(&(rhpx[sizeof(struct rhellomsg)]), + length - sizeof(struct rhellomsg)); + break; + case RMF_EHELLO: + (void)printf("endnode-hello "); + vers = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_vers); + eco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_eco); + ueco = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_ueco); + memcpy((char *)&srcea, (char *)&(cmp->cm_ehello.eh_src), + sizeof(srcea)); + src = EXTRACT_LE_16BITS(srcea.dne_remote.dne_nodeaddr); + info = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_info); + blksize = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_blksize); + /*seed*/ + memcpy((char *)&rtea, (char *)&(cmp->cm_ehello.eh_router), + sizeof(rtea)); + dst = EXTRACT_LE_16BITS(rtea.dne_remote.dne_nodeaddr); + hello = EXTRACT_LE_16BITS(cmp->cm_ehello.eh_hello); + other = EXTRACT_LE_8BITS(cmp->cm_ehello.eh_data); + print_i_info(info); + (void)printf( + "vers %d eco %d ueco %d src %s blksize %d rtr %s hello %d data %o", + vers, eco, ueco, dnaddr_string(src), + blksize, dnaddr_string(dst), hello, other); + break; + + default: + (void)printf("unknown control message"); + default_print((u_char *)rhp, length); + break; + } +} + +static void +print_t_info(int info) +{ + int ntype = info & 3; + switch (ntype) { + case 0: (void)printf("reserved-ntype? "); break; + case TI_L2ROUT: (void)printf("l2rout "); break; + case TI_L1ROUT: (void)printf("l1rout "); break; + case TI_ENDNODE: (void)printf("endnode "); break; + } + if (info & TI_VERIF) + (void)printf("verif "); + if (info & TI_BLOCK) + (void)printf("blo "); +} + +static void +print_l1_routes(const char *rp, u_int len) +{ + int count; + int id; + int info; + + /* The last short is a checksum */ + while (len > (3 * sizeof(short))) { + count = EXTRACT_LE_16BITS(rp); + if (count > 1024) + return; /* seems to be bogus from here on */ + rp += sizeof(short); + len -= sizeof(short); + id = EXTRACT_LE_16BITS(rp); + rp += sizeof(short); + len -= sizeof(short); + info = EXTRACT_LE_16BITS(rp); + rp += sizeof(short); + len -= sizeof(short); + (void)printf("{ids %d-%d cost %d hops %d} ", id, id + count, + RI_COST(info), RI_HOPS(info)); + } +} + +static void +print_l2_routes(const char *rp, u_int len) +{ + int count; + int area; + int info; + + /* The last short is a checksum */ + while (len > (3 * sizeof(short))) { + count = EXTRACT_LE_16BITS(rp); + if (count > 1024) + return; /* seems to be bogus from here on */ + rp += sizeof(short); + len -= sizeof(short); + area = EXTRACT_LE_16BITS(rp); + rp += sizeof(short); + len -= sizeof(short); + info = EXTRACT_LE_16BITS(rp); + rp += sizeof(short); + len -= sizeof(short); + (void)printf("{areas %d-%d cost %d hops %d} ", area, area + count, + RI_COST(info), RI_HOPS(info)); + } +} + +static void +print_i_info(int info) +{ + int ntype = info & II_TYPEMASK; + switch (ntype) { + case 0: (void)printf("reserved-ntype? "); break; + case II_L2ROUT: (void)printf("l2rout "); break; + case II_L1ROUT: (void)printf("l1rout "); break; + case II_ENDNODE: (void)printf("endnode "); break; + } + if (info & II_VERIF) + (void)printf("verif "); + if (info & II_NOMCAST) + (void)printf("nomcast "); + if (info & II_BLOCK) + (void)printf("blo "); +} + +static void +print_elist(const char *elp, u_int len) +{ + /* Not enough examples available for me to debug this */ +} + +static void +print_nsp(const u_char *nspp, u_int nsplen) +{ + const struct nsphdr *nsphp = (struct nsphdr *)nspp; + int dst, src, flags; + + flags = EXTRACT_LE_8BITS(nsphp->nh_flags); + dst = EXTRACT_LE_16BITS(nsphp->nh_dst); + src = EXTRACT_LE_16BITS(nsphp->nh_src); + + switch (flags & NSP_TYPEMASK) { + case MFT_DATA: + switch (flags & NSP_SUBMASK) { + case MFS_BOM: + case MFS_MOM: + case MFS_EOM: + case MFS_BOM+MFS_EOM: + printf("data %d>%d ", src, dst); + { + struct seghdr *shp = (struct seghdr *)nspp; + int ack; +#ifdef PRINT_NSPDATA + u_char *dp; +#endif + u_int data_off = sizeof(struct minseghdr); + + ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); + if (ack & SGQ_ACK) { /* acknum field */ + if ((ack & SGQ_NAK) == SGQ_NAK) + (void)printf("nak %d ", ack & SGQ_MASK); + else + (void)printf("ack %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); + data_off += sizeof(short); + if (ack & SGQ_OACK) { /* ackoth field */ + if ((ack & SGQ_ONAK) == SGQ_ONAK) + (void)printf("onak %d ", ack & SGQ_MASK); + else + (void)printf("oack %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); + data_off += sizeof(short); + } + } + (void)printf("seg %d ", ack & SGQ_MASK); +#ifdef PRINT_NSPDATA + dp = &(nspp[data_off]); + pdata(dp, 10); +#endif + } + break; + case MFS_ILS+MFS_INT: + printf("intr "); + { + struct seghdr *shp = (struct seghdr *)nspp; + int ack; +#ifdef PRINT_NSPDATA + u_char *dp; +#endif + u_int data_off = sizeof(struct minseghdr); + + ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); + if (ack & SGQ_ACK) { /* acknum field */ + if ((ack & SGQ_NAK) == SGQ_NAK) + (void)printf("nak %d ", ack & SGQ_MASK); + else + (void)printf("ack %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); + data_off += sizeof(short); + if (ack & SGQ_OACK) { /* ackdat field */ + if ((ack & SGQ_ONAK) == SGQ_ONAK) + (void)printf("nakdat %d ", ack & SGQ_MASK); + else + (void)printf("ackdat %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); + data_off += sizeof(short); + } + } + (void)printf("seg %d ", ack & SGQ_MASK); +#ifdef PRINT_NSPDATA + dp = &(nspp[data_off]); + pdata(dp, 10); +#endif + } + break; + case MFS_ILS: + (void)printf("link-service %d>%d ", src, dst); + { + struct seghdr *shp = (struct seghdr *)nspp; + struct lsmsg *lsmp = + (struct lsmsg *)&(nspp[sizeof(struct seghdr)]); + int ack; + int lsflags, fcval; + + ack = EXTRACT_LE_16BITS(shp->sh_seq[0]); + if (ack & SGQ_ACK) { /* acknum field */ + if ((ack & SGQ_NAK) == SGQ_NAK) + (void)printf("nak %d ", ack & SGQ_MASK); + else + (void)printf("ack %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(shp->sh_seq[1]); + if (ack & SGQ_OACK) { /* ackdat field */ + if ((ack & SGQ_ONAK) == SGQ_ONAK) + (void)printf("nakdat %d ", ack & SGQ_MASK); + else + (void)printf("ackdat %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(shp->sh_seq[2]); + } + } + (void)printf("seg %d ", ack & SGQ_MASK); + lsflags = EXTRACT_LE_8BITS(lsmp->ls_lsflags); + fcval = EXTRACT_LE_8BITS(lsmp->ls_fcval); + switch (lsflags & LSI_MASK) { + case LSI_DATA: + (void)printf("dat seg count %d ", fcval); + switch (lsflags & LSM_MASK) { + case LSM_NOCHANGE: + break; + case LSM_DONOTSEND: + (void)printf("donotsend-data "); + break; + case LSM_SEND: + (void)printf("send-data "); + break; + default: + (void)printf("reserved-fcmod? %x", lsflags); + break; + } + break; + case LSI_INTR: + (void)printf("intr req count %d ", fcval); + break; + default: + (void)printf("reserved-fcval-int? %x", lsflags); + break; + } + } + break; + default: + (void)printf("reserved-subtype? %x %d > %d", flags, src, dst); + break; + } + break; + case MFT_ACK: + switch (flags & NSP_SUBMASK) { + case MFS_DACK: + (void)printf("data-ack %d>%d ", src, dst); + { + struct ackmsg *amp = (struct ackmsg *)nspp; + int ack; + + ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); + if (ack & SGQ_ACK) { /* acknum field */ + if ((ack & SGQ_NAK) == SGQ_NAK) + (void)printf("nak %d ", ack & SGQ_MASK); + else + (void)printf("ack %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); + if (ack & SGQ_OACK) { /* ackoth field */ + if ((ack & SGQ_ONAK) == SGQ_ONAK) + (void)printf("onak %d ", ack & SGQ_MASK); + else + (void)printf("oack %d ", ack & SGQ_MASK); + } + } + } + break; + case MFS_IACK: + (void)printf("ils-ack %d>%d ", src, dst); + { + struct ackmsg *amp = (struct ackmsg *)nspp; + int ack; + + ack = EXTRACT_LE_16BITS(amp->ak_acknum[0]); + if (ack & SGQ_ACK) { /* acknum field */ + if ((ack & SGQ_NAK) == SGQ_NAK) + (void)printf("nak %d ", ack & SGQ_MASK); + else + (void)printf("ack %d ", ack & SGQ_MASK); + ack = EXTRACT_LE_16BITS(amp->ak_acknum[1]); + if (ack & SGQ_OACK) { /* ackdat field */ + if ((ack & SGQ_ONAK) == SGQ_ONAK) + (void)printf("nakdat %d ", ack & SGQ_MASK); + else + (void)printf("ackdat %d ", ack & SGQ_MASK); + } + } + } + break; + case MFS_CACK: + (void)printf("conn-ack %d", dst); + break; + default: + (void)printf("reserved-acktype? %x %d > %d", flags, src, dst); + break; + } + break; + case MFT_CTL: + switch (flags & NSP_SUBMASK) { + case MFS_CI: + case MFS_RCI: + if ((flags & NSP_SUBMASK) == MFS_CI) + (void)printf("conn-initiate "); + else + (void)printf("retrans-conn-initiate "); + (void)printf("%d>%d ", src, dst); + { + struct cimsg *cimp = (struct cimsg *)nspp; + int services, info, segsize; +#ifdef PRINT_NSPDATA + u_char *dp; +#endif + + services = EXTRACT_LE_8BITS(cimp->ci_services); + info = EXTRACT_LE_8BITS(cimp->ci_info); + segsize = EXTRACT_LE_16BITS(cimp->ci_segsize); + + switch (services & COS_MASK) { + case COS_NONE: + break; + case COS_SEGMENT: + (void)printf("seg "); + break; + case COS_MESSAGE: + (void)printf("msg "); + break; + case COS_CRYPTSER: + (void)printf("crypt "); + break; + } + switch (info & COI_MASK) { + case COI_32: + (void)printf("ver 3.2 "); + break; + case COI_31: + (void)printf("ver 3.1 "); + break; + case COI_40: + (void)printf("ver 4.0 "); + break; + case COI_41: + (void)printf("ver 4.1 "); + break; + } + (void)printf("segsize %d ", segsize); +#ifdef PRINT_NSPDATA + dp = &(nspp[sizeof(struct cimsg)]); + pdata(dp, nsplen - sizeof(struct cimsg)); +#endif + } + break; + case MFS_CC: + (void)printf("conn-confirm %d>%d ", src, dst); + { + struct ccmsg *ccmp = (struct ccmsg *)nspp; + int services, info; + u_int segsize, optlen; +#ifdef PRINT_NSPDATA + u_char *dp; +#endif + + services = EXTRACT_LE_8BITS(ccmp->cc_services); + info = EXTRACT_LE_8BITS(ccmp->cc_info); + segsize = EXTRACT_LE_16BITS(ccmp->cc_segsize); + optlen = EXTRACT_LE_8BITS(ccmp->cc_optlen); + + switch (services & COS_MASK) { + case COS_NONE: + break; + case COS_SEGMENT: + (void)printf("seg "); + break; + case COS_MESSAGE: + (void)printf("msg "); + break; + case COS_CRYPTSER: + (void)printf("crypt "); + break; + } + switch (info & COI_MASK) { + case COI_32: + (void)printf("ver 3.2 "); + break; + case COI_31: + (void)printf("ver 3.1 "); + break; + case COI_40: + (void)printf("ver 4.0 "); + break; + case COI_41: + (void)printf("ver 4.1 "); + break; + } + (void)printf("segsize %d ", segsize); + if (optlen) { + (void)printf("optlen %d ", optlen); +#ifdef PRINT_NSPDATA + optlen = min(optlen, nsplen - sizeof(struct ccmsg)); + dp = &(nspp[sizeof(struct ccmsg)]); + pdata(dp, optlen); +#endif + } + } + break; + case MFS_DI: + (void)printf("disconn-initiate %d>%d ", src, dst); + { + struct dimsg *dimp = (struct dimsg *)nspp; + int reason; + u_int optlen; +#ifdef PRINT_NSPDATA + u_char *dp; +#endif + + reason = EXTRACT_LE_16BITS(dimp->di_reason); + optlen = EXTRACT_LE_8BITS(dimp->di_optlen); + + print_reason(reason); + if (optlen) { + (void)printf("optlen %d ", optlen); +#ifdef PRINT_NSPDATA + optlen = min(optlen, nsplen - sizeof(struct dimsg)); + dp = &(nspp[sizeof(struct dimsg)]); + pdata(dp, optlen); +#endif + } + } + break; + case MFS_DC: + (void)printf("disconn-confirm %d>%d ", src, dst); + { + struct dcmsg *dcmp = (struct dcmsg *)nspp; + int reason; + + reason = EXTRACT_LE_16BITS(dcmp->dc_reason); + + print_reason(reason); + } + break; + default: + (void)printf("reserved-ctltype? %x %d > %d", flags, src, dst); + break; + } + break; + default: + (void)printf("reserved-type? %x %d > %d", flags, src, dst); + break; + } +} + +static struct tok reason2str[] = { + { UC_OBJREJECT, "object rejected connect" }, + { UC_RESOURCES, "insufficient resources" }, + { UC_NOSUCHNODE, "unrecognized node name" }, + { DI_SHUT, "node is shutting down" }, + { UC_NOSUCHOBJ, "unrecognized object" }, + { UC_INVOBJFORMAT, "invalid object name format" }, + { UC_OBJTOOBUSY, "object too busy" }, + { DI_PROTOCOL, "protocol error discovered" }, + { DI_TPA, "third party abort" }, + { UC_USERABORT, "user abort" }, + { UC_INVNODEFORMAT, "invalid node name format" }, + { UC_LOCALSHUT, "local node shutting down" }, + { DI_LOCALRESRC, "insufficient local resources" }, + { DI_REMUSERRESRC, "insufficient remote user resources" }, + { UC_ACCESSREJECT, "invalid access control information" }, + { DI_BADACCNT, "bad ACCOUNT information" }, + { UC_NORESPONSE, "no response from object" }, + { UC_UNREACHABLE, "node unreachable" }, + { DC_NOLINK, "no link terminate" }, + { DC_COMPLETE, "disconnect complete" }, + { DI_BADIMAGE, "bad image data in connect" }, + { DI_SERVMISMATCH, "cryptographic service mismatch" }, + { 0, NULL } +}; + +static void +print_reason(register int reason) +{ + printf("%s ", tok2str(reason2str, "reason-%d", reason)); +} + +char * +dnnum_string(u_short dnaddr) +{ + char *str; + int area = (u_short)(dnaddr & AREAMASK) >> AREASHIFT; + int node = dnaddr & NODEMASK; + + str = (char *)malloc(sizeof("00.0000")); + if (str == NULL) + error("dnnum_string: malloc"); + sprintf(str, "%d.%d", area, node); + return(str); +} + +char * +dnname_string(u_short dnaddr) +{ +#ifdef HAVE_LIBDNET + struct dn_naddr dna; + + dna.a_len = sizeof(short); + memcpy((char *)dna.a_addr, (char *)&dnaddr, sizeof(short)); + return (savestr(dnet_htoa(&dna))); +#else + return(dnnum_string(dnaddr)); /* punt */ +#endif +} + +#ifdef PRINT_NSPDATA +static void +pdata(u_char *dp, u_int maxlen) +{ + char c; + u_int x = maxlen; + + while (x-- > 0) { + c = *dp++; + if (isprint(c)) + putchar(c); + else + printf("\\%o", c & 0xFF); + } +} +#endif diff --git a/tcpdump.tproj/print-domain.c b/tcpdump.tproj/print-domain.c new file mode 100644 index 0000000..c6175ae --- /dev/null +++ b/tcpdump.tproj/print-domain.c @@ -0,0 +1,423 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-domain.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef NOERROR /* Solaris sucks */ +#undef T_UNSPEC /* SINIX does too */ +#include + +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +/* Compatibility */ +#ifndef T_TXT +#define T_TXT 16 /* text strings */ +#endif +#ifndef T_RP +#define T_RP 17 /* responsible person */ +#endif +#ifndef T_AFSDB +#define T_AFSDB 18 /* AFS cell database */ +#endif +#ifndef T_X25 +#define T_X25 19 /* X_25 calling address */ +#endif +#ifndef T_ISDN +#define T_ISDN 20 /* ISDN calling address */ +#endif +#ifndef T_RT +#define T_RT 21 /* router */ +#endif +#ifndef T_NSAP +#define T_NSAP 22 /* NSAP address */ +#endif +#ifndef T_NSAP_PTR +#define T_NSAP_PTR 23 /* reverse NSAP lookup (deprecated) */ +#endif +#ifndef T_SIG +#define T_SIG 24 /* security signature */ +#endif +#ifndef T_KEY +#define T_KEY 25 /* security key */ +#endif +#ifndef T_PX +#define T_PX 26 /* X.400 mail mapping */ +#endif +#ifndef T_GPOS +#define T_GPOS 27 /* geographical position (withdrawn) */ +#endif +#ifndef T_AAAA +#define T_AAAA 28 /* IP6 Address */ +#endif +#ifndef T_LOC +#define T_LOC 29 /* Location Information */ +#endif + +#ifndef T_UNSPEC +#define T_UNSPEC 103 /* Unspecified format (binary data) */ +#endif +#ifndef T_UNSPECA +#define T_UNSPECA 104 /* "unspecified ascii". Ugly MIT hack */ +#endif + +#ifndef C_CHAOS +#define C_CHAOS 3 /* for chaos net (MIT) */ +#endif +#ifndef C_HS +#define C_HS 4 /* for Hesiod name server (MIT) (XXX) */ +#endif + +static char *ns_ops[] = { + "", " inv_q", " stat", " op3", " notify", " op5", " op6", " op7", + " op8", " updataA", " updateD", " updateDA", + " updateM", " updateMA", " zoneInit", " zoneRef", +}; + +static char *ns_resp[] = { + "", " FormErr", " ServFail", " NXDomain", + " NotImp", " Refused", " Resp6", " Resp7", + " Resp8", " Resp9", " Resp10", " Resp11", + " Resp12", " Resp13", " Resp14", " NoChange", +}; + +/* skip over a domain name */ +static const u_char * +ns_nskip(register const u_char *cp, register const u_char *bp) +{ + register u_char i; + + if (((i = *cp++) & INDIR_MASK) == INDIR_MASK) + return (cp + 1); + while (i && cp < snapend) { + cp += i; + i = *cp++; + } + return (cp); +} + +/* print a */ +static const u_char * +ns_nprint(register const u_char *cp, register const u_char *bp) +{ + register u_int i; + register const u_char *rp; + register int compress; + + i = *cp++; + rp = cp + i; + if ((i & INDIR_MASK) == INDIR_MASK) { + rp = cp + 1; + compress = 1; + } else + compress = 0; + if (i != 0) + while (i && cp < snapend) { + if ((i & INDIR_MASK) == INDIR_MASK) { + cp = bp + (((i << 8) | *cp) & 0x3fff); + i = *cp++; + continue; + } + if (fn_printn(cp, i, snapend)) + break; + cp += i; + putchar('.'); + i = *cp++; + if (!compress) + rp += i + 1; + } + else + putchar('.'); + return (rp); +} + +/* print a */ +static const u_char * +ns_cprint(register const u_char *cp, register const u_char *bp) +{ + register u_int i; + + i = *cp++; + (void)fn_printn(cp, i, snapend); + return (cp + i); +} + +static struct tok type2str[] = { + { T_A, "A" }, + { T_NS, "NS" }, + { T_MD, "MD" }, + { T_MF, "MF" }, + { T_CNAME, "CNAME" }, + { T_SOA, "SOA" }, + { T_MB, "MB" }, + { T_MG, "MG" }, + { T_MR, "MR" }, + { T_NULL, "NULL" }, + { T_WKS, "WKS" }, + { T_PTR, "PTR" }, + { T_HINFO, "HINFO" }, + { T_MINFO, "MINFO" }, + { T_MX, "MX" }, + { T_TXT, "TXT" }, + { T_RP, "RP" }, + { T_AFSDB, "AFSDB" }, + { T_X25, "X25" }, + { T_ISDN, "ISDN" }, + { T_RT, "RT" }, + { T_NSAP, "NSAP" }, + { T_NSAP_PTR, "NSAP_PTR" }, + { T_SIG, "SIG" }, + { T_KEY, "KEY" }, + { T_PX, "PX" }, + { T_GPOS, "GPOS" }, + { T_AAAA, "AAAA" }, + { T_LOC , "LOC " }, + { T_UINFO, "UINFO" }, + { T_UID, "UID" }, + { T_GID, "GID" }, + { T_UNSPEC, "UNSPEC" }, + { T_UNSPECA, "UNSPECA" }, + { T_AXFR, "AXFR" }, + { T_MAILB, "MAILB" }, + { T_MAILA, "MAILA" }, + { T_ANY, "ANY" }, + { 0, NULL } +}; + +static struct tok class2str[] = { + { C_IN, "IN" }, /* Not used */ + { C_CHAOS, "CHAOS)" }, + { C_HS, "HS" }, + { C_ANY, "ANY" }, + { 0, NULL } +}; + +/* print a query */ +static void +ns_qprint(register const u_char *cp, register const u_char *bp) +{ + register const u_char *np = cp; + register u_int i; + + cp = ns_nskip(cp, bp); + + if (cp + 4 > snapend) + return; + + /* print the qtype and qclass (if it's not IN) */ + i = *cp++ << 8; + i |= *cp++; + printf(" %s", tok2str(type2str, "Type%d", i)); + i = *cp++ << 8; + i |= *cp++; + if (i != C_IN) + printf(" %s", tok2str(class2str, "(Class %d)", i)); + + fputs("? ", stdout); + ns_nprint(np, bp); +} + +/* print a reply */ +static const u_char * +ns_rprint(register const u_char *cp, register const u_char *bp) +{ + register u_int i; + register u_short typ, len; + register const u_char *rp; + + if (vflag) { + putchar(' '); + cp = ns_nprint(cp, bp); + } else + cp = ns_nskip(cp, bp); + + if (cp + 10 > snapend) + return (snapend); + + /* print the type/qtype and class (if it's not IN) */ + typ = *cp++ << 8; + typ |= *cp++; + i = *cp++ << 8; + i |= *cp++; + if (i != C_IN) + printf(" %s", tok2str(class2str, "(Class %d)", i)); + + /* ignore ttl */ + cp += 4; + + len = *cp++ << 8; + len |= *cp++; + + rp = cp + len; + + printf(" %s", tok2str(type2str, "Type%d", typ)); + switch (typ) { + + case T_A: + printf(" %s", ipaddr_string(cp)); + break; + + case T_NS: + case T_CNAME: + case T_PTR: + putchar(' '); + (void)ns_nprint(cp, bp); + break; + + case T_MX: + putchar(' '); + (void)ns_nprint(cp + 2, bp); + printf(" %d", EXTRACT_16BITS(cp)); + break; + + case T_TXT: + putchar(' '); + (void)ns_cprint(cp, bp); + break; + + case T_UNSPECA: /* One long string */ + printf(" %.*s", len, cp); + break; + } + return (rp); /* XXX This isn't always right */ +} + +void +ns_print(register const u_char *bp, u_int length) +{ + register const HEADER *np; + register int qdcount, ancount, nscount, arcount; + register const u_char *cp; + + np = (const HEADER *)bp; + /* get the byte-order right */ + qdcount = ntohs(np->qdcount); + ancount = ntohs(np->ancount); + nscount = ntohs(np->nscount); + arcount = ntohs(np->arcount); + + if (np->qr) { + /* this is a response */ + printf(" %d%s%s%s%s%s", + ntohs(np->id), + ns_ops[np->opcode], + ns_resp[np->rcode], + np->aa? "*" : "", + np->ra? "" : "-", + np->tc? "|" : ""); + if (qdcount != 1) + printf(" [%dq]", qdcount); + /* Print QUESTION section on -vv */ + if (vflag > 1) { + fputs(" q: ", stdout); + cp = ns_nprint((const u_char *)(np + 1), bp); + } else + cp = ns_nskip((const u_char *)(np + 1), bp); + printf(" %d/%d/%d", ancount, nscount, arcount); + if (ancount--) { + cp = ns_rprint(cp + 4, bp); + while (ancount-- && cp < snapend) { + putchar(','); + cp = ns_rprint(cp, bp); + } + } + } + else { + /* this is a request */ + printf(" %d%s%s", + ntohs(np->id), + ns_ops[np->opcode], + np->rd? "+" : ""); + + /* any weirdness? */ + if (*(((u_short *)np)+1) & htons(0x6ff)) + printf(" [b2&3=0x%x]", ntohs(*(((u_short *)np)+1))); + + if (np->opcode == IQUERY) { + if (qdcount) + printf(" [%dq]", qdcount); + if (ancount != 1) + printf(" [%da]", ancount); + } + else { + if (ancount) + printf(" [%da]", ancount); + if (qdcount != 1) + printf(" [%dq]", qdcount); + } + if (nscount) + printf(" [%dn]", nscount); + if (arcount) + printf(" [%dau]", arcount); + + ns_qprint((const u_char *)(np + 1), (const u_char *)np); + } + printf(" (%d)", length); +} diff --git a/tcpdump.tproj/print-dvmrp.c b/tcpdump.tproj/print-dvmrp.c new file mode 100644 index 0000000..a396cf9 --- /dev/null +++ b/tcpdump.tproj/print-dvmrp.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-dvmrp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +/* + * DVMRP message types and flag values shamelessly stolen from + * mrouted/dvmrp.h. + */ +#define DVMRP_PROBE 1 /* for finding neighbors */ +#define DVMRP_REPORT 2 /* for reporting some or all routes */ +#define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ + /* + * of this router's neighbors + */ +#define DVMRP_NEIGHBORS 4 /* response to such a request */ +#define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ +#define DVMRP_NEIGHBORS2 6 +#define DVMRP_PRUNE 7 /* prune message */ +#define DVMRP_GRAFT 8 /* graft message */ +#define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ + +/* + * 'flags' byte values in DVMRP_NEIGHBORS2 reply. + */ +#define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ +#define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ +#define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ +#define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ +#define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ + +static void print_probe(const u_char *, const u_char *, u_int); +static void print_report(const u_char *, const u_char *, u_int); +static void print_neighbors(const u_char *, const u_char *, u_int); +static void print_neighbors2(const u_char *, const u_char *, u_int); +static void print_prune(const u_char *, const u_char *, u_int); +static void print_graft(const u_char *, const u_char *, u_int); +static void print_graft_ack(const u_char *, const u_char *, u_int); + +static u_int32_t target_level; + +void +dvmrp_print(register const u_char *bp, register u_int len) +{ + register const u_char *ep; + register u_char type; + + ep = (const u_char *)snapend; + if (bp >= ep) + return; + + type = bp[1]; + bp += 8; + /* + * Skip IGMP header + */ + + len -= 8; + + switch (type) { + + case DVMRP_PROBE: + printf(" Probe"); + if (vflag) + print_probe(bp, ep, len); + break; + + case DVMRP_REPORT: + printf(" Report"); + if (vflag) + print_report(bp, ep, len); + break; + + case DVMRP_ASK_NEIGHBORS: + printf(" Ask-neighbors(old)"); + break; + + case DVMRP_NEIGHBORS: + printf(" Neighbors(old)"); + print_neighbors(bp, ep, len); + break; + + case DVMRP_ASK_NEIGHBORS2: + printf(" Ask-neighbors2"); + break; + + case DVMRP_NEIGHBORS2: + printf(" Neighbors2"); + /* + * extract version and capabilities from IGMP group + * address field + */ + bp -= 4; + target_level = (bp[0] << 24) | (bp[1] << 16) | + (bp[2] << 8) | bp[3]; + bp += 4; + print_neighbors2(bp, ep, len); + break; + + case DVMRP_PRUNE: + printf(" Prune"); + print_prune(bp, ep, len); + break; + + case DVMRP_GRAFT: + printf(" Graft"); + print_graft(bp, ep, len); + break; + + case DVMRP_GRAFT_ACK: + printf(" Graft-ACK"); + print_graft_ack(bp, ep, len); + break; + + default: + printf(" [type %d]", type); + break; + } +} + +static void +print_report(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + register u_int32_t mask, origin; + register int metric, i, width, done; + + while (len > 0) { + if (len < 3) { + printf(" [|]"); + return; + } + mask = (u_int32_t)0xff << 24 | bp[0] << 16 | bp[1] << 8 | bp[2]; + width = 1; + if (bp[0]) + width = 2; + if (bp[1]) + width = 3; + if (bp[2]) + width = 4; + + printf("\n\tMask %s", intoa(htonl(mask))); + bp += 3; + len -= 3; + do { + if (bp + width + 1 > ep) { + printf(" [|]"); + return; + } + if (len < width + 1) { + printf("\n\t [Truncated Report]"); + return; + } + origin = 0; + for (i = 0; i < width; ++i) + origin = origin << 8 | *bp++; + for ( ; i < 4; ++i) + origin <<= 8; + + metric = *bp++; + done = metric & 0x80; + metric &= 0x7f; + printf("\n\t %s metric %d", intoa(htonl(origin)), + metric); + len -= width + 1; + } while (!done); + } +} + +#define GET_ADDR(to) (memcpy((char *)to, (char *)bp, 4), bp += 4) + +static void +print_probe(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + register u_int32_t genid; + u_char neighbor[4]; + + if ((len < 4) || ((bp + 4) > ep)) { + /* { (ctags) */ + printf(" [|}"); + return; + } + genid = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3]; + bp += 4; + len -= 4; + printf("\n\tgenid %u", genid); + + while ((len > 0) && (bp < ep)) { + if ((len < 4) || ((bp + 4) > ep)) { + printf(" [|]"); + return; + } + GET_ADDR(neighbor); + len -= 4; + printf("\n\tneighbor %s", ipaddr_string(neighbor)); + } +} + +static void +print_neighbors(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + u_char laddr[4], neighbor[4]; + register u_char metric; + register u_char thresh; + register int ncount; + + while (len > 0 && bp < ep) { + if (len < 7 || (bp + 7) >= ep) { + printf(" [|]"); + return; + } + GET_ADDR(laddr); + metric = *bp++; + thresh = *bp++; + ncount = *bp++; + len -= 7; + while (--ncount >= 0 && (len >= 4) && (bp + 4) < ep) { + GET_ADDR(neighbor); + printf(" [%s ->", ipaddr_string(laddr)); + printf(" %s, (%d/%d)]", + ipaddr_string(neighbor), metric, thresh); + len -= 4; + } + } +} + +static void +print_neighbors2(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + u_char laddr[4], neighbor[4]; + register u_char metric, thresh, flags; + register int ncount; + + printf(" (v %d.%d):", + (int)target_level & 0xff, + (int)(target_level >> 8) & 0xff); + + while (len > 0 && bp < ep) { + if (len < 8 || (bp + 8) >= ep) { + printf(" [|]"); + return; + } + GET_ADDR(laddr); + metric = *bp++; + thresh = *bp++; + flags = *bp++; + ncount = *bp++; + len -= 8; + while (--ncount >= 0 && (len >= 4) && (bp + 4) <= ep) { + GET_ADDR(neighbor); + printf(" [%s -> ", ipaddr_string(laddr)); + printf("%s (%d/%d", ipaddr_string(neighbor), + metric, thresh); + if (flags & DVMRP_NF_TUNNEL) + printf("/tunnel"); + if (flags & DVMRP_NF_SRCRT) + printf("/srcrt"); + if (flags & DVMRP_NF_QUERIER) + printf("/querier"); + if (flags & DVMRP_NF_DISABLED) + printf("/disabled"); + if (flags & DVMRP_NF_DOWN) + printf("/down"); + printf(")]"); + len -= 4; + } + if (ncount != -1) { + printf(" [|]"); + return; + } + } +} + +static void +print_prune(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + union a { + u_char b[4]; + u_int32_t i; + } prune_timer; + + if (len < 12 || (bp + 12) > ep) { + printf(" [|]"); + return; + } + printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); + bp += 8; + GET_ADDR(prune_timer.b); + printf(" timer %d", (int)ntohl(prune_timer.i)); +} + +static void +print_graft(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + + if (len < 8 || (bp + 8) > ep) { + printf(" [|]"); + return; + } + printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); +} + +static void +print_graft_ack(register const u_char *bp, register const u_char *ep, + register u_int len) +{ + + if (len < 8 || (bp + 8) > ep) { + printf(" [|]"); + return; + } + printf(" src %s grp %s", ipaddr_string(bp), ipaddr_string(bp + 4)); +} diff --git a/tcpdump.tproj/print-egp.c b/tcpdump.tproj/print-egp.c new file mode 100644 index 0000000..092c2b5 --- /dev/null +++ b/tcpdump.tproj/print-egp.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Lawrence Berkeley Laboratory, + * Berkeley, CA. The name of the University may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Initial contribution from Jeff Honig (jch@MITCHELL.CIT.CORNELL.EDU). + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-egp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +struct egp_packet { + u_char egp_version; +#define EGP_VERSION 2 + u_char egp_type; +#define EGPT_ACQUIRE 3 +#define EGPT_REACH 5 +#define EGPT_POLL 2 +#define EGPT_UPDATE 1 +#define EGPT_ERROR 8 + u_char egp_code; +#define EGPC_REQUEST 0 +#define EGPC_CONFIRM 1 +#define EGPC_REFUSE 2 +#define EGPC_CEASE 3 +#define EGPC_CEASEACK 4 +#define EGPC_HELLO 0 +#define EGPC_HEARDU 1 + u_char egp_status; +#define EGPS_UNSPEC 0 +#define EGPS_ACTIVE 1 +#define EGPS_PASSIVE 2 +#define EGPS_NORES 3 +#define EGPS_ADMIN 4 +#define EGPS_GODOWN 5 +#define EGPS_PARAM 6 +#define EGPS_PROTO 7 +#define EGPS_INDET 0 +#define EGPS_UP 1 +#define EGPS_DOWN 2 +#define EGPS_UNSOL 0x80 + u_short egp_checksum; + u_short egp_as; + u_short egp_sequence; + union { + u_short egpu_hello; + u_char egpu_gws[2]; + u_short egpu_reason; +#define EGPR_UNSPEC 0 +#define EGPR_BADHEAD 1 +#define EGPR_BADDATA 2 +#define EGPR_NOREACH 3 +#define EGPR_XSPOLL 4 +#define EGPR_NORESP 5 +#define EGPR_UVERSION 6 + } egp_handg; +#define egp_hello egp_handg.egpu_hello +#define egp_intgw egp_handg.egpu_gws[0] +#define egp_extgw egp_handg.egpu_gws[1] +#define egp_reason egp_handg.egpu_reason + union { + u_short egpu_poll; + u_int32_t egpu_sourcenet; + } egp_pands; +#define egp_poll egp_pands.egpu_poll +#define egp_sourcenet egp_pands.egpu_sourcenet +}; + +char *egp_acquire_codes[] = { + "request", + "confirm", + "refuse", + "cease", + "cease_ack" +}; + +char *egp_acquire_status[] = { + "unspecified", + "active_mode", + "passive_mode", + "insufficient_resources", + "administratively_prohibited", + "going_down", + "parameter_violation", + "protocol_violation" +}; + +char *egp_reach_codes[] = { + "hello", + "i-h-u" +}; + +char *egp_status_updown[] = { + "indeterminate", + "up", + "down" +}; + +char *egp_reasons[] = { + "unspecified", + "bad_EGP_header_format", + "bad_EGP_data_field_format", + "reachability_info_unavailable", + "excessive_polling_rate", + "no_response", + "unsupported_version" +}; + +static void +egpnrprint(register const struct egp_packet *egp, register u_int length) +{ + register const u_char *cp; + u_int32_t addr; + register u_int32_t net; + register u_int netlen; + int gateways, distances, networks; + int t_gateways; + char *comma; + + addr = egp->egp_sourcenet; + if (IN_CLASSA(addr)) { + net = addr & IN_CLASSA_NET; + netlen = 1; + } else if (IN_CLASSB(addr)) { + net = addr & IN_CLASSB_NET; + netlen = 2; + } else if (IN_CLASSC(addr)) { + net = addr & IN_CLASSC_NET; + netlen = 3; + } else { + net = 0; + netlen = 0; + } + cp = (u_char *)(egp + 1); + + t_gateways = egp->egp_intgw + egp->egp_extgw; + for (gateways = 0; gateways < t_gateways; ++gateways) { + /* Pickup host part of gateway address */ + addr = 0; + TCHECK2(cp[0], 4 - netlen); + switch (netlen) { + + case 1: + addr = *cp++; + /* fall through */ + case 2: + addr = (addr << 8) | *cp++; + /* fall through */ + case 3: + addr = (addr << 8) | *cp++; + } + addr |= net; + TCHECK2(cp[0], 1); + distances = *cp++; + printf(" %s %s ", + gateways < (int)egp->egp_intgw ? "int" : "ext", + ipaddr_string(&addr)); + + comma = ""; + putchar('('); + while (--distances >= 0) { + TCHECK2(cp[0], 2); + printf("%sd%d:", comma, (int)*cp++); + comma = ", "; + networks = *cp++; + while (--networks >= 0) { + /* Pickup network number */ + TCHECK2(cp[0], 1); + addr = (u_int32_t)*cp++ << 24; + if (IN_CLASSB(addr)) { + TCHECK2(cp[0], 1); + addr |= (u_int32_t)*cp++ << 16; + } else if (!IN_CLASSA(addr)) { + TCHECK2(cp[0], 2); + addr |= (u_int32_t)*cp++ << 16; + addr |= (u_int32_t)*cp++ << 8; + } + printf(" %s", ipaddr_string(&addr)); + } + } + putchar(')'); + } + return; +trunc: + fputs("[|]", stdout); +} + +void +egp_print(register const u_char *bp, register u_int length, + register const u_char *bp2) +{ + register const struct egp_packet *egp; + register const struct ip *ip; + register int status; + register int code; + register int type; + + egp = (struct egp_packet *)bp; + ip = (struct ip *)bp2; + (void)printf("%s > %s: egp: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + if (egp->egp_version != EGP_VERSION) { + printf("[version %d]", egp->egp_version); + return; + } + printf("as:%d seq:%d", ntohs(egp->egp_as), ntohs(egp->egp_sequence)); + + type = egp->egp_type; + code = egp->egp_code; + status = egp->egp_status; + + switch (type) { + case EGPT_ACQUIRE: + printf(" acquire"); + switch (code) { + case EGPC_REQUEST: + case EGPC_CONFIRM: + printf(" %s", egp_acquire_codes[code]); + switch (status) { + case EGPS_UNSPEC: + case EGPS_ACTIVE: + case EGPS_PASSIVE: + printf(" %s", egp_acquire_status[status]); + break; + + default: + printf(" [status %d]", status); + break; + } + printf(" hello:%d poll:%d", + ntohs(egp->egp_hello), + ntohs(egp->egp_poll)); + break; + + case EGPC_REFUSE: + case EGPC_CEASE: + case EGPC_CEASEACK: + printf(" %s", egp_acquire_codes[code]); + switch (status ) { + case EGPS_UNSPEC: + case EGPS_NORES: + case EGPS_ADMIN: + case EGPS_GODOWN: + case EGPS_PARAM: + case EGPS_PROTO: + printf(" %s", egp_acquire_status[status]); + break; + + default: + printf("[status %d]", status); + break; + } + break; + + default: + printf("[code %d]", code); + break; + } + break; + + case EGPT_REACH: + switch (code) { + + case EGPC_HELLO: + case EGPC_HEARDU: + printf(" %s", egp_reach_codes[code]); + if (status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d]", status); + break; + + default: + printf("[reach code %d]", code); + break; + } + break; + + case EGPT_POLL: + printf(" poll"); + if (egp->egp_status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d]", status); + printf(" net:%s", ipaddr_string(&egp->egp_sourcenet)); + break; + + case EGPT_UPDATE: + printf(" update"); + if (status & EGPS_UNSOL) { + status &= ~EGPS_UNSOL; + printf(" unsolicited"); + } + if (status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d]", status); + printf(" %s int %d ext %d", + ipaddr_string(&egp->egp_sourcenet), + egp->egp_intgw, + egp->egp_extgw); + if (vflag) + egpnrprint(egp, length); + break; + + case EGPT_ERROR: + printf(" error"); + if (status <= EGPS_DOWN) + printf(" state:%s", egp_status_updown[status]); + else + printf(" [status %d]", status); + + if (ntohs(egp->egp_reason) <= EGPR_UVERSION) + printf(" %s", egp_reasons[ntohs(egp->egp_reason)]); + else + printf(" [reason %d]", ntohs(egp->egp_reason)); + break; + + default: + printf("[type %d]", type); + break; + } +} diff --git a/tcpdump.tproj/print-ether.c b/tcpdump.tproj/print-ether.c new file mode 100644 index 0000000..ae9ddd9 --- /dev/null +++ b/tcpdump.tproj/print-ether.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ether.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ethertype.h" + +const u_char *packetp; +const u_char *snapend; + +static inline void +ether_print(register const u_char *bp, u_int length) +{ + register const struct ether_header *ep; + + ep = (const struct ether_header *)bp; + if (qflag) + (void)printf("%s %s %d: ", + etheraddr_string(ESRC(ep)), + etheraddr_string(EDST(ep)), + length); + else + (void)printf("%s %s %s %d: ", + etheraddr_string(ESRC(ep)), + etheraddr_string(EDST(ep)), + etherproto_string(ep->ether_type), + length); +} + +/* + * This is the top level routine of the printer. 'p' is the points + * to the ether header of the packet, 'tvp' is the timestamp, + * 'length' is the length of the packet off the wire, and 'caplen' + * is the number of bytes actually captured. + */ +void +ether_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + u_int caplen = h->caplen; + u_int length = h->len; + struct ether_header *ep; + u_short ether_type; + extern u_short extracted_ethertype; + + ts_print(&h->ts); + + if (caplen < sizeof(struct ether_header)) { + printf("[|ether]"); + goto out; + } + + if (eflag) + ether_print(p, length); + + /* + * Some printers want to get back at the ethernet addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = p; + snapend = p + caplen; + + length -= sizeof(struct ether_header); + caplen -= sizeof(struct ether_header); + ep = (struct ether_header *)p; + p += sizeof(struct ether_header); + + ether_type = ntohs(ep->ether_type); + + /* + * Is it (gag) an 802.3 encapsulation? + */ + extracted_ethertype = 0; + if (ether_type < ETHERMTU) { + /* Try to print the LLC-layer header & higher layers */ + if (llc_print(p, length, caplen, ESRC(ep), EDST(ep)) == 0) { + /* ether_type not known, print raw packet */ + if (!eflag) + ether_print((u_char *)ep, length); + if (extracted_ethertype) { + printf("(LLC %s) ", + etherproto_string(htons(extracted_ethertype))); + } + if (!xflag && !qflag) + default_print(p, caplen); + } + } else if (ether_encap_print(ether_type, p, length, caplen) == 0) { + /* ether_type not known, print raw packet */ + if (!eflag) + ether_print((u_char *)ep, length + sizeof(*ep)); + if (!xflag && !qflag) + default_print(p, caplen); + } + if (xflag) + default_print(p, caplen); + out: + putchar('\n'); +} + +/* + * Prints the packet encapsulated in an Ethernet data segment + * (or an equivalent encapsulation), given the Ethernet type code. + * + * Returns non-zero if it can do so, zero if the ethertype is unknown. + * + * Stuffs the ether type into a global for the benefit of lower layers + * that might want to know what it is. + */ + +u_short extracted_ethertype; + +int +ether_encap_print(u_short ethertype, const u_char *p, + u_int length, u_int caplen) +{ + extracted_ethertype = ethertype; + + switch (ethertype) { + + case ETHERTYPE_IP: + ip_print(p, length); + return (1); + + case ETHERTYPE_ARP: + case ETHERTYPE_REVARP: + arp_print(p, length, caplen); + return (1); + + case ETHERTYPE_DN: + decnet_print(p, length, caplen); + return (1); + + case ETHERTYPE_ATALK: + if (vflag) + fputs("et1 ", stdout); + atalk_print(p, length); + return (1); + + case ETHERTYPE_AARP: + aarp_print(p, length); + return (1); + + case ETHERTYPE_LAT: + case ETHERTYPE_SCA: + case ETHERTYPE_MOPRC: + case ETHERTYPE_MOPDL: + /* default_print for now */ + default: + return (0); + } +} diff --git a/tcpdump.tproj/print-fddi.c b/tcpdump.tproj/print-fddi.c new file mode 100644 index 0000000..15f8297 --- /dev/null +++ b/tcpdump.tproj/print-fddi.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-fddi.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#ifdef HAVE_FDDI +#include +#include +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ethertype.h" + +#include "fddi.h" + +/* + * Some FDDI interfaces use bit-swapped addresses. + */ +#if defined(ultrix) || defined(__alpha) +int fddi_bitswap = 0; +#else +int fddi_bitswap = 1; +#endif + +/* + * FDDI support for tcpdump, by Jeffrey Mogul [DECWRL], June 1992 + * + * Based in part on code by Van Jacobson, which bears this note: + * + * NOTE: This is a very preliminary hack for FDDI support. + * There are all sorts of wired in constants & nothing (yet) + * to print SMT packets as anything other than hex dumps. + * Most of the necessary changes are waiting on my redoing + * the "header" that a kernel fddi driver supplies to bpf: I + * want it to look like one byte of 'direction' (0 or 1 + * depending on whether the packet was inbound or outbound), + * two bytes of system/driver dependent data (anything an + * implementor thinks would be useful to filter on and/or + * save per-packet, then the real 21-byte FDDI header. + * Steve McCanne & I have also talked about adding the + * 'direction' byte to all bpf headers (e.g., in the two + * bytes of padding on an ethernet header). It's not clear + * we could do this in a backwards compatible way & we hate + * the idea of an incompatible bpf change. Discussions are + * proceeding. + * + * Also, to really support FDDI (and better support 802.2 + * over ethernet) we really need to re-think the rather simple + * minded assumptions about fixed length & fixed format link + * level headers made in gencode.c. One day... + * + * - vj + */ + +#define FDDI_HDRLEN (sizeof(struct fddi_header)) + +static u_char fddi_bit_swap[] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, +}; + +/* + * Print FDDI frame-control bits + */ +static inline void +print_fddi_fc(u_char fc) +{ + switch (fc) { + + case FDDIFC_VOID: /* Void frame */ + printf("void "); + break; + + case FDDIFC_NRT: /* Nonrestricted token */ + printf("nrt "); + break; + + case FDDIFC_RT: /* Restricted token */ + printf("rt "); + break; + + case FDDIFC_SMT_INFO: /* SMT Info */ + printf("info "); + break; + + case FDDIFC_SMT_NSA: /* SMT Next station adrs */ + printf("nsa "); + break; + + case FDDIFC_MAC_BEACON: /* MAC Beacon frame */ + printf("beacon "); + break; + + case FDDIFC_MAC_CLAIM: /* MAC Claim frame */ + printf("claim "); + break; + + default: + switch (fc & FDDIFC_CLFF) { + + case FDDIFC_MAC: + printf("mac%1x ", fc & FDDIFC_ZZZZ); + break; + + case FDDIFC_SMT: + printf("smt%1x ", fc & FDDIFC_ZZZZ); + break; + + case FDDIFC_LLC_ASYNC: + printf("async%1x ", fc & FDDIFC_ZZZZ); + break; + + case FDDIFC_LLC_SYNC: + printf("sync%1x ", fc & FDDIFC_ZZZZ); + break; + + case FDDIFC_IMP_ASYNC: + printf("imp_async%1x ", fc & FDDIFC_ZZZZ); + break; + + case FDDIFC_IMP_SYNC: + printf("imp_sync%1x ", fc & FDDIFC_ZZZZ); + break; + + default: + printf("%02x ", fc); + break; + } + } +} + +/* Extract src, dst addresses */ +static inline void +extract_fddi_addrs(const struct fddi_header *fddip, char *fsrc, char *fdst) +{ + register int i; + + if (fddi_bitswap) { + /* + * bit-swap the fddi addresses (isn't the IEEE standards + * process wonderful!) then convert them to names. + */ + for (i = 0; i < 6; ++i) + fdst[i] = fddi_bit_swap[fddip->fddi_dhost[i]]; + for (i = 0; i < 6; ++i) + fsrc[i] = fddi_bit_swap[fddip->fddi_shost[i]]; + } + else { + memcpy(fdst, (char *)fddip->fddi_dhost, 6); + memcpy(fsrc, (char *)fddip->fddi_shost, 6); + } +} + +/* + * Print the FDDI MAC header + */ +static inline void +fddi_print(register const struct fddi_header *fddip, register u_int length, + register const u_char *fsrc, register const u_char *fdst) +{ + char *srcname, *dstname; + + srcname = etheraddr_string(fsrc); + dstname = etheraddr_string(fdst); + + if (vflag) + (void) printf("%02x %s %s %d: ", + fddip->fddi_fc, + srcname, dstname, + length); + else if (qflag) + printf("%s %s %d: ", srcname, dstname, length); + else { + (void) print_fddi_fc(fddip->fddi_fc); + (void) printf("%s %s %d: ", srcname, dstname, length); + } +} + +static inline void +fddi_smt_print(const u_char *p, u_int length) +{ + printf(""); +} + +/* + * This is the top level routine of the printer. 'sp' is the points + * to the FDDI header of the packet, 'tvp' is the timestamp, + * 'length' is the length of the packet off the wire, and 'caplen' + * is the number of bytes actually captured. + */ +void +fddi_if_print(u_char *pcap, const struct pcap_pkthdr *h, + register const u_char *p) +{ + u_int caplen = h->caplen; + u_int length = h->len; + const struct fddi_header *fddip = (struct fddi_header *)p; + extern u_short extracted_ethertype; + struct ether_header ehdr; + + ts_print(&h->ts); + + if (caplen < FDDI_HDRLEN) { + printf("[|fddi]"); + goto out; + } + /* + * Get the FDDI addresses into a canonical form + */ + extract_fddi_addrs(fddip, (char *)ESRC(&ehdr), (char *)EDST(&ehdr)); + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + snapend = p + caplen; + /* + * Actually, the only printer that uses packetp is print-bootp.c, + * and it assumes that packetp points to an Ethernet header. The + * right thing to do is to fix print-bootp.c to know which link + * type is in use when it excavates. XXX + */ + packetp = (u_char *)&ehdr; + + if (eflag) + fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr)); + + /* Skip over FDDI MAC header */ + length -= FDDI_HDRLEN; + p += FDDI_HDRLEN; + caplen -= FDDI_HDRLEN; + + /* Frame Control field determines interpretation of packet */ + extracted_ethertype = 0; + if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_LLC_ASYNC) { + /* Try to print the LLC-layer header & higher layers */ + if (llc_print(p, length, caplen, ESRC(&ehdr), EDST(&ehdr)) + == 0) { + /* + * Some kinds of LLC packet we cannot + * handle intelligently + */ + if (!eflag) + fddi_print(fddip, length, + ESRC(&ehdr), EDST(&ehdr)); + if (extracted_ethertype) { + printf("(LLC %s) ", + etherproto_string(htons(extracted_ethertype))); + } + if (!xflag && !qflag) + default_print(p, caplen); + } + } else if ((fddip->fddi_fc & FDDIFC_CLFF) == FDDIFC_SMT) + fddi_smt_print(p, caplen); + else { + /* Some kinds of FDDI packet we cannot handle intelligently */ + if (!eflag) + fddi_print(fddip, length, ESRC(&ehdr), EDST(&ehdr)); + if (!xflag && !qflag) + default_print(p, caplen); + } + if (xflag) + default_print(p, caplen); +out: + putchar('\n'); +} +#else +#include +#include + +#include + +#include "interface.h" +void +fddi_if_print(u_char *pcap, const struct pcap_pkthdr *h, + register const u_char *p) +{ + + error("not configured for fddi"); + /* NOTREACHED */ +} +#endif diff --git a/tcpdump.tproj/print-gre.c b/tcpdump.tproj/print-gre.c new file mode 100644 index 0000000..94e42db --- /dev/null +++ b/tcpdump.tproj/print-gre.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Lawrence Berkeley Laboratory, + * Berkeley, CA. The name of the University may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Initial contribution from John Hawkinson + * + * This module implements support for decoding GRE (Generic Routing + * Encapsulation) tunnels; they're documented in RFC1701 and RFC1702. + * This code only supports the IP encapsulation thereof. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-gre.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $"; +#endif + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +#define GRE_SIZE (20) + +struct gre { + u_short flags; + u_short proto; + union { + struct gre_ckof { + u_short cksum; + u_short offset; + } gre_ckof; + u_int32_t key; + u_int32_t seq; + } gre_void1; + union { + u_int32_t key; + u_int32_t seq; + u_int32_t routing; + } gre_void2; + union { + u_int32_t seq; + u_int32_t routing; + } gre_void3; + union { + u_int32_t routing; + } gre_void4; +}; + +#define GRE_CP 0x8000 /* Checksum Present */ +#define GRE_RP 0x4000 /* Routing Present */ +#define GRE_KP 0x2000 /* Key Present */ +#define GRE_SP 0x1000 /* Sequence Present */ + + +#define GREPROTO_IP 0x0800 + + +/* + * Deencapsulate and print a GRE-tunneled IP datagram + */ +void +gre_print(const u_char *bp, u_int length) +{ + const u_char *cp = bp + 4; + const struct gre *gre; + u_short flags, proto; + + gre = (const struct gre *)bp; + + if (length < GRE_SIZE) { + goto trunc; + } + flags = EXTRACT_16BITS(&gre->flags); + proto = EXTRACT_16BITS(&gre->proto); + + if (vflag) { + /* Decode the flags */ + putchar('['); + if (flags & GRE_CP) + putchar('C'); + if (flags & GRE_RP) + putchar('R'); + if (flags & GRE_KP) + putchar('K'); + if (flags & GRE_SP) + putchar('S'); + fputs("] ", stdout); + } + /* Checksum & Offset are present */ + if ((flags & GRE_CP) | (flags & GRE_RP)) + cp += 4; + + /* We don't support routing fields (variable length) now. Punt. */ + if (flags & GRE_RP) + return; + + if (flags & GRE_KP) + cp += 4; + if (flags & GRE_SP) + cp += 4; + + switch (proto) { + + case GREPROTO_IP: + ip_print(cp, length - ((cp - bp) / sizeof(u_char))); + break; + + default: + printf("gre-proto-0x%04X", proto); + break; + } + return; + +trunc: + fputs("[|gre]", stdout); + +} diff --git a/tcpdump.tproj/print-icmp.c b/tcpdump.tproj/print-icmp.c new file mode 100644 index 0000000..d4eb3fa --- /dev/null +++ b/tcpdump.tproj/print-icmp.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-icmp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +/* rfc1700 */ +#ifndef ICMP_UNREACH_NET_UNKNOWN +#define ICMP_UNREACH_NET_UNKNOWN 6 /* destination net unknown */ +#endif +#ifndef ICMP_UNREACH_HOST_UNKNOWN +#define ICMP_UNREACH_HOST_UNKNOWN 7 /* destination host unknown */ +#endif +#ifndef ICMP_UNREACH_ISOLATED +#define ICMP_UNREACH_ISOLATED 8 /* source host isolated */ +#endif +#ifndef ICMP_UNREACH_NET_PROHIB +#define ICMP_UNREACH_NET_PROHIB 9 /* admin prohibited net */ +#endif +#ifndef ICMP_UNREACH_HOST_PROHIB +#define ICMP_UNREACH_HOST_PROHIB 10 /* admin prohibited host */ +#endif +#ifndef ICMP_UNREACH_TOSNET +#define ICMP_UNREACH_TOSNET 11 /* tos prohibited net */ +#endif +#ifndef ICMP_UNREACH_TOSHOST +#define ICMP_UNREACH_TOSHOST 12 /* tos prohibited host */ +#endif + +/* rfc1716 */ +#ifndef ICMP_UNREACH_FILTER_PROHIB +#define ICMP_UNREACH_FILTER_PROHIB 13 /* admin prohibited filter */ +#endif +#ifndef ICMP_UNREACH_HOST_PRECEDENCE +#define ICMP_UNREACH_HOST_PRECEDENCE 14 /* host precedence violation */ +#endif +#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF +#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15 /* precedence cutoff */ +#endif + +/* rfc1256 */ +#ifndef ICMP_ROUTERADVERT +#define ICMP_ROUTERADVERT 9 /* router advertisement */ +#endif +#ifndef ICMP_ROUTERSOLICIT +#define ICMP_ROUTERSOLICIT 10 /* router solicitation */ +#endif + +/* Most of the icmp types */ +static struct tok icmp2str[] = { + { ICMP_ECHOREPLY, "echo reply" }, + { ICMP_SOURCEQUENCH, "source quench" }, + { ICMP_ECHO, "echo request" }, + { ICMP_ROUTERSOLICIT, "router solicitation" }, + { ICMP_TSTAMP, "time stamp request" }, + { ICMP_TSTAMPREPLY, "time stamp reply" }, + { ICMP_IREQ, "information request" }, + { ICMP_IREQREPLY, "information reply" }, + { ICMP_MASKREQ, "address mask request" }, + { 0, NULL } +}; + +/* Formats for most of the ICMP_UNREACH codes */ +static struct tok unreach2str[] = { + { ICMP_UNREACH_NET, "net %s unreachable" }, + { ICMP_UNREACH_HOST, "host %s unreachable" }, + { ICMP_UNREACH_SRCFAIL, + "%s unreachable - source route failed" }, + { ICMP_UNREACH_NET_UNKNOWN, "net %s unreachable - unknown" }, + { ICMP_UNREACH_HOST_UNKNOWN, "host %s unreachable - unknown" }, + { ICMP_UNREACH_ISOLATED, + "%s unreachable - source host isolated" }, + { ICMP_UNREACH_NET_PROHIB, + "net %s unreachable - admin prohibited" }, + { ICMP_UNREACH_HOST_PROHIB, + "host %s unreachable - admin prohibited" }, + { ICMP_UNREACH_TOSNET, + "net %s unreachable - tos prohibited" }, + { ICMP_UNREACH_TOSHOST, + "host %s unreachable - tos prohibited" }, + { ICMP_UNREACH_FILTER_PROHIB, + "host %s unreachable - admin prohibited filter" }, + { ICMP_UNREACH_HOST_PRECEDENCE, + "host %s unreachable - host precedence violation" }, + { ICMP_UNREACH_PRECEDENCE_CUTOFF, + "host %s unreachable - precedence cutoff" }, + { 0, NULL } +}; + +/* Formats for the ICMP_REDIRECT codes */ +static struct tok type2str[] = { + { ICMP_REDIRECT_NET, "redirect %s to net %s" }, + { ICMP_REDIRECT_HOST, "redirect %s to host %s" }, + { ICMP_REDIRECT_TOSNET, "redirect-tos %s to net %s" }, + { ICMP_REDIRECT_TOSHOST, "redirect-tos %s to net %s" }, + { 0, NULL } +}; + +/* rfc1191 */ +struct mtu_discovery { + short unused; + short nexthopmtu; +}; + +/* rfc1256 */ +struct ih_rdiscovery { + u_char ird_addrnum; + u_char ird_addrsiz; + u_short ird_lifetime; +}; + +struct id_rdiscovery { + u_int32_t ird_addr; + u_int32_t ird_pref; +}; + +void +icmp_print(register const u_char *bp, register const u_char *bp2) +{ + register char *cp; + register const struct icmp *dp; + register const struct ip *ip; + register const char *str, *fmt; + register const struct ip *oip; + register const struct udphdr *ouh; + register u_int hlen, dport, mtu; + char buf[256]; + + dp = (struct icmp *)bp; + ip = (struct ip *)bp2; + str = buf; + + (void)printf("%s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + TCHECK(dp->icmp_code); + switch (dp->icmp_type) { + + case ICMP_UNREACH: + TCHECK(dp->icmp_ip.ip_dst); + switch (dp->icmp_code) { + + case ICMP_UNREACH_PROTOCOL: + TCHECK(dp->icmp_ip.ip_p); + (void)sprintf(buf, "%s protocol %d unreachable", + ipaddr_string(&dp->icmp_ip.ip_dst), + dp->icmp_ip.ip_p); + break; + + case ICMP_UNREACH_PORT: + TCHECK(dp->icmp_ip.ip_p); + oip = &dp->icmp_ip; + hlen = oip->ip_hl * 4; + ouh = (struct udphdr *)(((u_char *)oip) + hlen); + dport = ntohs(ouh->uh_dport); + switch (oip->ip_p) { + + case IPPROTO_TCP: + (void)sprintf(buf, + "%s tcp port %s unreachable", + ipaddr_string(&oip->ip_dst), + tcpport_string(dport)); + break; + + case IPPROTO_UDP: + (void)sprintf(buf, + "%s udp port %s unreachable", + ipaddr_string(&oip->ip_dst), + udpport_string(dport)); + break; + + default: + (void)sprintf(buf, + "%s protocol %d port %d unreachable", + ipaddr_string(&oip->ip_dst), + oip->ip_p, dport); + break; + } + break; + + case ICMP_UNREACH_NEEDFRAG: + { + register const struct mtu_discovery *mp; + + mp = (struct mtu_discovery *)&dp->icmp_void; + mtu = EXTRACT_16BITS(&mp->nexthopmtu); + if (mtu) + (void)sprintf(buf, + "%s unreachable - need to frag (mtu %d)", + ipaddr_string(&dp->icmp_ip.ip_dst), mtu); + else + (void)sprintf(buf, + "%s unreachable - need to frag", + ipaddr_string(&dp->icmp_ip.ip_dst)); + } + break; + + default: + fmt = tok2str(unreach2str, "#%d %%s unreachable", + dp->icmp_code); + (void)sprintf(buf, fmt, + ipaddr_string(&dp->icmp_ip.ip_dst)); + break; + } + break; + + case ICMP_REDIRECT: + TCHECK(dp->icmp_ip.ip_dst); + fmt = tok2str(type2str, "redirect-#%d %%s to net %%s", + dp->icmp_code); + (void)sprintf(buf, fmt, + ipaddr_string(&dp->icmp_ip.ip_dst), + ipaddr_string(&dp->icmp_gwaddr)); + break; + + case ICMP_ROUTERADVERT: + { + register const struct ih_rdiscovery *ihp; + register const struct id_rdiscovery *idp; + u_int lifetime, num, size; + + (void)strcpy(buf, "router advertisement"); + cp = buf + strlen(buf); + + ihp = (struct ih_rdiscovery *)&dp->icmp_void; + TCHECK(*ihp); + (void)strcpy(cp, " lifetime "); + cp = buf + strlen(buf); + lifetime = EXTRACT_16BITS(&ihp->ird_lifetime); + if (lifetime < 60) + (void)sprintf(cp, "%u", lifetime); + else if (lifetime < 60 * 60) + (void)sprintf(cp, "%u:%02u", + lifetime / 60, lifetime % 60); + else + (void)sprintf(cp, "%u:%02u:%02u", + lifetime / 3600, + (lifetime % 3600) / 60, + lifetime % 60); + cp = buf + strlen(buf); + + num = ihp->ird_addrnum; + (void)sprintf(cp, " %d:", num); + cp = buf + strlen(buf); + + size = ihp->ird_addrsiz; + if (size != 2) { + (void)sprintf(cp, " [size %d]", size); + break; + } + idp = (struct id_rdiscovery *)&dp->icmp_data; + while (num-- > 0) { + TCHECK(*idp); + (void)sprintf(cp, " {%s %u}", + ipaddr_string(&idp->ird_addr), + EXTRACT_32BITS(&idp->ird_pref)); + cp = buf + strlen(buf); + } + } + break; + + case ICMP_TIMXCEED: + TCHECK(dp->icmp_ip.ip_dst); + switch (dp->icmp_code) { + + case ICMP_TIMXCEED_INTRANS: + str = "time exceeded in-transit"; + break; + + case ICMP_TIMXCEED_REASS: + str = "ip reassembly time exceeded"; + break; + + default: + (void)sprintf(buf, "time exceeded-#%d", dp->icmp_code); + break; + } + break; + + case ICMP_PARAMPROB: + if (dp->icmp_code) + (void)sprintf(buf, "parameter problem - code %d", + dp->icmp_code); + else { + TCHECK(dp->icmp_pptr); + (void)sprintf(buf, "parameter problem - octet %d", + dp->icmp_pptr); + } + break; + + case ICMP_MASKREPLY: + TCHECK(dp->icmp_mask); + (void)sprintf(buf, "address mask is 0x%08x", + (u_int32_t)ntohl(dp->icmp_mask)); + break; + + default: + str = tok2str(icmp2str, "type-#%d", dp->icmp_type); + break; + } + (void)printf("icmp: %s", str); + return; +trunc: + fputs("[|icmp]", stdout); +} diff --git a/tcpdump.tproj/print-igrp.c b/tcpdump.tproj/print-igrp.c new file mode 100644 index 0000000..a35e6ac --- /dev/null +++ b/tcpdump.tproj/print-igrp.c @@ -0,0 +1,161 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Initial contribution from Francis Dupont (francis.dupont@inria.fr) + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-igrp.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "addrtoname.h" +#include "interface.h" +#include "igrp.h" +#include "extract.h" /* must come after interface.h */ + +static void +igrp_entry_print(register struct igrprte *igr, register int is_interior, + register int is_exterior) +{ + register u_int delay, bandwidth; + u_int metric, mtu; + + if (is_interior) + printf(" *.%d.%d.%d", igr->igr_net[0], + igr->igr_net[1], igr->igr_net[2]); + else if (is_exterior) + printf(" X%d.%d.%d.0", igr->igr_net[0], + igr->igr_net[1], igr->igr_net[2]); + else + printf(" %d.%d.%d.0", igr->igr_net[0], + igr->igr_net[1], igr->igr_net[2]); + + delay = EXTRACT_24BITS(igr->igr_dly); + bandwidth = EXTRACT_24BITS(igr->igr_bw); + metric = bandwidth + delay; + if (metric > 0xffffff) + metric = 0xffffff; + mtu = EXTRACT_16BITS(igr->igr_mtu); + + printf(" d=%d b=%d r=%d l=%d M=%d mtu=%d in %d hops", + 10 * delay, bandwidth == 0 ? 0 : 10000000 / bandwidth, + igr->igr_rel, igr->igr_ld, metric, + mtu, igr->igr_hct); +} + +static struct tok op2str[] = { + { IGRP_UPDATE, "update" }, + { IGRP_REQUEST, "request" }, + { 0, NULL } +}; + +void +igrp_print(register const u_char *bp, u_int length, register const u_char *bp2) +{ + register struct igrphdr *hdr; + register struct ip *ip; + register u_char *cp; + u_int nint, nsys, next; + + hdr = (struct igrphdr *)bp; + ip = (struct ip *)bp2; + cp = (u_char *)(hdr + 1); + (void)printf("%s > %s: igrp: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + /* Header */ + TCHECK(*hdr); + nint = EXTRACT_16BITS(&hdr->ig_ni); + nsys = EXTRACT_16BITS(&hdr->ig_ns); + next = EXTRACT_16BITS(&hdr->ig_nx); + + (void)printf(" %s V%d edit=%d AS=%d (%d/%d/%d)", + tok2str(op2str, "op-#%d", hdr->ig_op), + hdr->ig_v, + hdr->ig_ed, + EXTRACT_16BITS(&hdr->ig_as), + nint, + nsys, + next); + + length -= sizeof(*hdr); + while (length >= IGRP_RTE_SIZE) { + if (nint > 0) { + TCHECK2(*cp, IGRP_RTE_SIZE); + igrp_entry_print((struct igrprte *)cp, 1, 0); + --nint; + } else if (nsys > 0) { + TCHECK2(*cp, IGRP_RTE_SIZE); + igrp_entry_print((struct igrprte *)cp, 0, 0); + --nsys; + } else if (next > 0) { + TCHECK2(*cp, IGRP_RTE_SIZE); + igrp_entry_print((struct igrprte *)cp, 0, 1); + --next; + } else { + (void)printf("[extra bytes %d]", length); + break; + } + cp += IGRP_RTE_SIZE; + length -= IGRP_RTE_SIZE; + } + if (nint == 0 && nsys == 0 && next == 0) + return; +trunc: + fputs("[|igrp]", stdout); +} diff --git a/tcpdump.tproj/print-ip.c b/tcpdump.tproj/print-ip.c new file mode 100644 index 0000000..6c0c31c --- /dev/null +++ b/tcpdump.tproj/print-ip.c @@ -0,0 +1,547 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ip.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "addrtoname.h" +#include "interface.h" +#include "extract.h" /* must come after interface.h */ + +/* Compatibility */ +#ifndef IPPROTO_ND +#define IPPROTO_ND 77 +#endif + +#ifndef IN_CLASSD +#define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000) +#endif + +/* (following from ipmulti/mrouted/prune.h) */ + +/* + * The packet format for a traceroute request. + */ +struct tr_query { + u_int tr_src; /* traceroute source */ + u_int tr_dst; /* traceroute destination */ + u_int tr_raddr; /* traceroute response address */ +#ifdef WORDS_BIGENDIAN + struct { + u_int ttl : 8; /* traceroute response ttl */ + u_int qid : 24; /* traceroute query id */ + } q; +#else + struct { + u_int qid : 24; /* traceroute query id */ + u_int ttl : 8; /* traceroute response ttl */ + } q; +#endif +}; + +#define tr_rttl q.ttl +#define tr_qid q.qid + +/* + * Traceroute response format. A traceroute response has a tr_query at the + * beginning, followed by one tr_resp for each hop taken. + */ +struct tr_resp { + u_int tr_qarr; /* query arrival time */ + u_int tr_inaddr; /* incoming interface address */ + u_int tr_outaddr; /* outgoing interface address */ + u_int tr_rmtaddr; /* parent address in source tree */ + u_int tr_vifin; /* input packet count on interface */ + u_int tr_vifout; /* output packet count on interface */ + u_int tr_pktcnt; /* total incoming packets for src-grp */ + u_char tr_rproto; /* routing proto deployed on router */ + u_char tr_fttl; /* ttl required to forward on outvif */ + u_char tr_smask; /* subnet mask for src addr */ + u_char tr_rflags; /* forwarding error codes */ +}; + +/* defs within mtrace */ +#define TR_QUERY 1 +#define TR_RESP 2 + +/* fields for tr_rflags (forwarding error codes) */ +#define TR_NO_ERR 0 +#define TR_WRONG_IF 1 +#define TR_PRUNED 2 +#define TR_OPRUNED 3 +#define TR_SCOPED 4 +#define TR_NO_RTE 5 +#define TR_NO_FWD 7 +#define TR_NO_SPACE 0x81 +#define TR_OLD_ROUTER 0x82 + +/* fields for tr_rproto (routing protocol) */ +#define TR_PROTO_DVMRP 1 +#define TR_PROTO_MOSPF 2 +#define TR_PROTO_PIM 3 +#define TR_PROTO_CBT 4 + +static void print_mtrace(register const u_char *bp, register u_int len) +{ + register struct tr_query *tr = (struct tr_query *)(bp + 8); + + printf("mtrace %d: %s to %s reply-to %s", tr->tr_qid, + ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), + ipaddr_string(&tr->tr_raddr)); + if (IN_CLASSD(ntohl(tr->tr_raddr))) + printf(" with-ttl %d", tr->tr_rttl); +} + +static void print_mresp(register const u_char *bp, register u_int len) +{ + register struct tr_query *tr = (struct tr_query *)(bp + 8); + + printf("mresp %d: %s to %s reply-to %s", tr->tr_qid, + ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst), + ipaddr_string(&tr->tr_raddr)); + if (IN_CLASSD(ntohl(tr->tr_raddr))) + printf(" with-ttl %d", tr->tr_rttl); +} + +static void +igmp_print(register const u_char *bp, register u_int len, + register const u_char *bp2) +{ + register const struct ip *ip; + + ip = (const struct ip *)bp2; + (void)printf("%s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + TCHECK2(bp[0], 8); + switch (bp[0]) { + case 0x11: + (void)printf("igmp query"); + if (*(int *)&bp[4]) + (void)printf(" [gaddr %s]", ipaddr_string(&bp[4])); + if (len != 8) + (void)printf(" [len %d]", len); + break; + case 0x12: + (void)printf("igmp report %s", ipaddr_string(&bp[4])); + if (len != 8) + (void)printf(" [len %d]", len); + break; + case 0x16: + (void)printf("igmp nreport %s", ipaddr_string(&bp[4])); + break; + case 0x17: + (void)printf("igmp leave %s", ipaddr_string(&bp[4])); + break; + case 0x13: + (void)printf("igmp dvmrp"); + if (len < 8) + (void)printf(" [len %d]", len); + else + dvmrp_print(bp, len); + break; + case 0x14: + (void)printf("igmp pim"); + pim_print(bp, len); + break; + case 0x1e: + print_mresp(bp, len); + break; + case 0x1f: + print_mtrace(bp, len); + break; + default: + (void)printf("igmp-%d", bp[0] & 0xf); + break; + } + if ((bp[0] >> 4) != 1) + (void)printf(" [v%d]", bp[0] >> 4); + + TCHECK2(bp[0], len); + if (vflag) { + /* Check the IGMP checksum */ + u_int32_t sum = 0; + int count; + const u_short *sp = (u_short *)bp; + + for (count = len / 2; --count >= 0; ) + sum += *sp++; + if (len & 1) + sum += ntohs(*(u_char *) sp << 8); + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + sum = 0xffff & ~sum; + if (sum != 0) + printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2])); + } + return; +trunc: + fputs("[|igmp]", stdout); +} + +/* + * print the recorded route in an IP RR, LSRR or SSRR option. + */ +static void +ip_printroute(const char *type, register const u_char *cp, u_int length) +{ + register u_int ptr = cp[2] - 1; + register u_int len; + + printf(" %s{", type); + if ((length + 1) & 3) + printf(" [bad length %d]", length); + if (ptr < 3 || ((ptr + 1) & 3) || ptr > length + 1) + printf(" [bad ptr %d]", cp[2]); + + type = ""; + for (len = 3; len < length; len += 4) { + if (ptr == len) + type = "#"; + printf("%s%s", type, ipaddr_string(&cp[len])); + type = " "; + } + printf("%s}", ptr == len? "#" : ""); +} + +/* + * print IP options. + */ +static void +ip_optprint(register const u_char *cp, u_int length) +{ + register u_int len; + + for (; length > 0; cp += len, length -= len) { + int tt = *cp; + + len = (tt == IPOPT_NOP || tt == IPOPT_EOL) ? 1 : cp[1]; + if (len <= 0) { + printf("[|ip op len %d]", len); + return; + } + if (&cp[1] >= snapend || cp + len > snapend) { + printf("[|ip]"); + return; + } + switch (tt) { + + case IPOPT_EOL: + printf(" EOL"); + if (length > 1) + printf("-%d", length - 1); + return; + + case IPOPT_NOP: + printf(" NOP"); + break; + + case IPOPT_TS: + printf(" TS{%d}", len); + break; + + case IPOPT_SECURITY: + printf(" SECURITY{%d}", len); + break; + + case IPOPT_RR: + printf(" RR{%d}=", len); + ip_printroute("RR", cp, len); + break; + + case IPOPT_SSRR: + ip_printroute("SSRR", cp, len); + break; + + case IPOPT_LSRR: + ip_printroute("LSRR", cp, len); + break; + + default: + printf(" IPOPT-%d{%d}", cp[0], len); + break; + } + } +} + +/* + * compute an IP header checksum. + * don't modifiy the packet. + */ +static int +in_cksum(const struct ip *ip) +{ + register const u_short *sp = (u_short *)ip; + register u_int32_t sum = 0; + register int count; + + /* + * No need for endian conversions. + */ + for (count = ip->ip_hl * 2; --count >= 0; ) + sum += *sp++; + while (sum > 0xffff) + sum = (sum & 0xffff) + (sum >> 16); + sum = ~sum & 0xffff; + + return (sum); +} + +/* + * print an IP datagram. + */ +void +ip_print(register const u_char *bp, register u_int length) +{ + register const struct ip *ip; + register u_int hlen, len, off; + register const u_char *cp; + + ip = (const struct ip *)bp; +#ifdef LBL_ALIGN + /* + * If the IP header is not aligned, copy into abuf. + * This will never happen with BPF. It does happen raw packet + * dumps from -r. + */ + if ((long)ip & 3) { + static u_char *abuf = NULL; + static int didwarn = 0; + + if (abuf == NULL) { + abuf = (u_char *)malloc(snaplen); + if (abuf == NULL) + error("ip_print: malloc"); + } + memcpy((char *)abuf, (char *)ip, min(length, snaplen)); + snapend += abuf - (u_char *)ip; + packetp = abuf; + ip = (struct ip *)abuf; + /* We really want libpcap to give us aligned packets */ + if (!didwarn) { + warning("compensating for unaligned libpcap packets"); + ++didwarn; + } + } +#endif + if ((u_char *)(ip + 1) > snapend) { + printf("[|ip]"); + return; + } + if (length < sizeof (struct ip)) { + (void)printf("truncated-ip %d", length); + return; + } + hlen = ip->ip_hl * 4; + + len = ntohs(ip->ip_len); + if (length < len) + (void)printf("truncated-ip - %d bytes missing!", + len - length); + len -= hlen; + + /* + * If this is fragment zero, hand it to the next higher + * level protocol. + */ + off = ntohs(ip->ip_off); + if ((off & 0x1fff) == 0) { + cp = (const u_char *)ip + hlen; + switch (ip->ip_p) { + + case IPPROTO_TCP: + tcp_print(cp, len, (const u_char *)ip); + break; + + case IPPROTO_UDP: + udp_print(cp, len, (const u_char *)ip); + break; + + case IPPROTO_ICMP: + icmp_print(cp, (const u_char *)ip); + break; + +#ifndef IPPROTO_IGRP +#define IPPROTO_IGRP 9 +#endif + case IPPROTO_IGRP: + igrp_print(cp, len, (const u_char *)ip); + break; + + case IPPROTO_ND: + (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + (void)printf(" nd %d", len); + break; + + case IPPROTO_EGP: + egp_print(cp, len, (const u_char *)ip); + break; + +#ifndef IPPROTO_OSPF +#define IPPROTO_OSPF 89 +#endif + case IPPROTO_OSPF: + ospf_print(cp, len, (const u_char *)ip); + break; + +#ifndef IPPROTO_IGMP +#define IPPROTO_IGMP 2 +#endif + case IPPROTO_IGMP: + igmp_print(cp, len, (const u_char *)ip); + break; + +#ifndef IPPROTO_ENCAP +#define IPPROTO_ENCAP 4 +#endif + case IPPROTO_ENCAP: + /* ip-in-ip encapsulation */ + if (vflag) + (void)printf("%s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + ip_print(cp, len); + if (! vflag) { + printf(" (encap)"); + return; + } + break; + +#ifndef IPPROTO_GRE +#define IPPROTO_GRE 47 +#endif + case IPPROTO_GRE: + if (vflag) + (void)printf("gre %s > %s: ", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + /* do it */ + gre_print(cp, len); + if (! vflag) { + printf(" (gre encap)"); + return; + } + break; + + default: + (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + (void)printf(" ip-proto-%d %d", ip->ip_p, len); + break; + } + } + /* + * for fragmented datagrams, print id:size@offset. On all + * but the last stick a "+". For unfragmented datagrams, note + * the don't fragment flag. + */ + if (off & 0x3fff) { + /* + * if this isn't the first frag, we're missing the + * next level protocol header. print the ip addr. + */ + if (off & 0x1fff) + (void)printf("%s > %s:", ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + (void)printf(" (frag %d:%d@%d%s)", ntohs(ip->ip_id), len, + (off & 0x1fff) * 8, + (off & IP_MF)? "+" : ""); + } else if (off & IP_DF) + (void)printf(" (DF)"); + + if (ip->ip_tos) + (void)printf(" [tos 0x%x]", (int)ip->ip_tos); + if (ip->ip_ttl <= 1) + (void)printf(" [ttl %d]", (int)ip->ip_ttl); + + if (vflag) { + int sum; + char *sep = ""; + + printf(" ("); + if (ip->ip_ttl > 1) { + (void)printf("%sttl %d", sep, (int)ip->ip_ttl); + sep = ", "; + } + if ((off & 0x3fff) == 0) { + (void)printf("%sid %d", sep, (int)ntohs(ip->ip_id)); + sep = ", "; + } + if ((u_char *)ip + hlen <= snapend) { + sum = in_cksum(ip); + if (sum != 0) { + (void)printf("%sbad cksum %x!", sep, + ntohs(ip->ip_sum)); + sep = ", "; + } + } + if ((hlen -= sizeof(struct ip)) > 0) { + (void)printf("%soptlen=%d", sep, hlen); + ip_optprint((u_char *)(ip + 1), hlen); + } + printf(")"); + } +} diff --git a/tcpdump.tproj/print-ipx.c b/tcpdump.tproj/print-ipx.c new file mode 100644 index 0000000..f526160 --- /dev/null +++ b/tcpdump.tproj/print-ipx.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print Novell IPX packets. + * Contributed by Brad Parker (brad@fcr.com). + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ipx.c,v 1.1.1.1 1999/05/02 03:58:33 wsanchez Exp $"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#endif +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ipx.h" +#include "extract.h" + + +static const char *ipxaddr_string(u_int32_t, const u_char *); +void ipx_decode(const struct ipxHdr *, const u_char *, u_int); +void ipx_sap_print(const u_short *, u_int); +void ipx_rip_print(const u_short *, u_int); + +/* + * Print IPX datagram packets. + */ +void +ipx_print(const u_char *p, u_int length) +{ + const struct ipxHdr *ipx = (const struct ipxHdr *)p; + + TCHECK(ipx->srcSkt); + (void)printf("%s.%x > ", + ipxaddr_string(EXTRACT_32BITS(ipx->srcNet), ipx->srcNode), + EXTRACT_16BITS(&ipx->srcSkt)); + + (void)printf("%s.%x:", + ipxaddr_string(EXTRACT_32BITS(ipx->dstNet), ipx->dstNode), + EXTRACT_16BITS(&ipx->dstSkt)); + + /* take length from ipx header */ + TCHECK(ipx->length); + length = EXTRACT_16BITS(&ipx->length); + + ipx_decode(ipx, (u_char *)ipx + ipxSize, length - ipxSize); + return; +trunc: + printf("[|ipx %d]", length); +} + +static const char * +ipxaddr_string(u_int32_t net, const u_char *node) +{ + static char line[256]; + + sprintf(line, "%x.%02x:%02x:%02x:%02x:%02x:%02x", + net, node[0], node[1], node[2], node[3], node[4], node[5]); + + return line; +} + +void +ipx_decode(const struct ipxHdr *ipx, const u_char *datap, u_int length) +{ + register u_short dstSkt; + + dstSkt = EXTRACT_16BITS(&ipx->dstSkt); + switch (dstSkt) { + case IPX_SKT_NCP: + (void)printf(" ipx-ncp %d", length); + break; + case IPX_SKT_SAP: + ipx_sap_print((u_short *)datap, length); + break; + case IPX_SKT_RIP: + ipx_rip_print((u_short *)datap, length); + break; + case IPX_SKT_NETBIOS: + (void)printf(" ipx-netbios %d", length); + break; + case IPX_SKT_DIAGNOSTICS: + (void)printf(" ipx-diags %d", length); + break; + default: + (void)printf(" ipx-#%x %d", dstSkt, length); + break; + } +} + +void +ipx_sap_print(const u_short *ipx, u_int length) +{ + int command, i; + + TCHECK(ipx[0]); + command = EXTRACT_16BITS(ipx); + ipx++; + length -= 2; + + switch (command) { + case 1: + case 3: + if (command == 1) + (void)printf("ipx-sap-req"); + else + (void)printf("ipx-sap-nearest-req"); + + if (length > 0) { + TCHECK(ipx[1]); + (void)printf(" %x '", EXTRACT_16BITS(&ipx[0])); + fn_print((u_char *)&ipx[1], (u_char *)&ipx[1] + 48); + putchar('\''); + } + break; + + case 2: + case 4: + if (command == 2) + (void)printf("ipx-sap-resp"); + else + (void)printf("ipx-sap-nearest-resp"); + + for (i = 0; i < 8 && length > 0; i++) { + TCHECK2(ipx[27], 1); + (void)printf(" %x '", EXTRACT_16BITS(&ipx[0])); + fn_print((u_char *)&ipx[1], (u_char *)&ipx[1] + 48); + printf("' addr %s", + ipxaddr_string(EXTRACT_32BITS(&ipx[25]), (u_char *)&ipx[27])); + ipx += 32; + length -= 64; + } + break; + default: + (void)printf("ipx-sap-?%x", command); + break; + } + return; +trunc: + printf("[|ipx %d]", length); +} + +void +ipx_rip_print(const u_short *ipx, u_int length) +{ + int command, i; + + TCHECK(ipx[0]); + command = EXTRACT_16BITS(ipx); + ipx++; + length -= 2; + + switch (command) { + case 1: + (void)printf("ipx-rip-req"); + if (length > 0) { + TCHECK(ipx[3]); + (void)printf(" %u/%d.%d", EXTRACT_32BITS(&ipx[0]), + EXTRACT_16BITS(&ipx[2]), EXTRACT_16BITS(&ipx[3])); + } + break; + case 2: + (void)printf("ipx-rip-resp"); + for (i = 0; i < 50 && length > 0; i++) { + TCHECK(ipx[3]); + (void)printf(" %u/%d.%d", EXTRACT_32BITS(&ipx[0]), + EXTRACT_16BITS(&ipx[2]), EXTRACT_16BITS(&ipx[3])); + + ipx += 4; + length -= 8; + } + break; + default: + (void)printf("ipx-rip-?%x", command); + } + return; +trunc: + printf("[|ipx %d]", length); +} + diff --git a/tcpdump.tproj/print-isoclns.c b/tcpdump.tproj/print-isoclns.c new file mode 100644 index 0000000..cea4a7e --- /dev/null +++ b/tcpdump.tproj/print-isoclns.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Original code by Matt Thomas, Digital Equipment Corporation + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-isoclns.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" +#include "ethertype.h" + +#define CLNS 129 +#define ESIS 130 +#define ISIS 131 +#define NULLNS 0 + +static int osi_cksum(const u_char *, u_int, const u_char *, u_char *, u_char *); +static void esis_print(const u_char *, u_int); + +void +isoclns_print(const u_char *p, u_int length, u_int caplen, + const u_char *esrc, const u_char *edst) +{ + if (caplen < 1) { + printf("[|iso-clns] "); + if (!eflag) + printf("%s > %s", + etheraddr_string(esrc), + etheraddr_string(edst)); + return; + } + + switch (*p) { + + case CLNS: + /* esis_print(&p, &length); */ + printf("iso-clns"); + if (!eflag) + (void)printf(" %s > %s", + etheraddr_string(esrc), + etheraddr_string(edst)); + break; + + case ESIS: + printf("iso-esis"); + if (!eflag) + (void)printf(" %s > %s", + etheraddr_string(esrc), + etheraddr_string(edst)); + esis_print(p, length); + return; + + case ISIS: + printf("iso-isis"); + if (!eflag) + (void)printf(" %s > %s", + etheraddr_string(esrc), + etheraddr_string(edst)); + /* isis_print(&p, &length); */ + (void)printf(" len=%d ", length); + if (caplen > 1) + default_print_unaligned(p, caplen); + break; + + case NULLNS: + printf("iso-nullns"); + if (!eflag) + (void)printf(" %s > %s", + etheraddr_string(esrc), + etheraddr_string(edst)); + break; + + default: + printf("iso-clns %02x", p[0]); + if (!eflag) + (void)printf(" %s > %s", + etheraddr_string(esrc), + etheraddr_string(edst)); + (void)printf(" len=%d ", length); + if (caplen > 1) + default_print_unaligned(p, caplen); + break; + } +} + +#define ESIS_REDIRECT 6 +#define ESIS_ESH 2 +#define ESIS_ISH 4 + +struct esis_hdr { + u_char version; + u_char reserved; + u_char type; + u_char tmo[2]; + u_char cksum[2]; +}; + +static void +esis_print(const u_char *p, u_int length) +{ + const u_char *ep; + int li = p[1]; + const struct esis_hdr *eh = (const struct esis_hdr *) &p[2]; + u_char cksum[2]; + u_char off[2]; + + if (length == 2) { + if (qflag) + printf(" bad pkt!"); + else + printf(" no header at all!"); + return; + } + ep = p + li; + if (li > length) { + if (qflag) + printf(" bad pkt!"); + else + printf(" LI(%d) > PDU size (%d)!", li, length); + return; + } + if (li < sizeof(struct esis_hdr) + 2) { + if (qflag) + printf(" bad pkt!"); + else { + printf(" too short for esis header %d:", li); + while (--length >= 0) + printf("%02X", *p++); + } + return; + } + switch (eh->type & 0x1f) { + + case ESIS_REDIRECT: + printf(" redirect"); + break; + + case ESIS_ESH: + printf(" esh"); + break; + + case ESIS_ISH: + printf(" ish"); + break; + + default: + printf(" type %d", eh->type & 0x1f); + break; + } + off[0] = eh->cksum[0]; + off[1] = eh->cksum[1]; + if (vflag && osi_cksum(p, li, eh->cksum, cksum, off)) { + printf(" bad cksum (got %02x%02x want %02x%02x)", + eh->cksum[1], eh->cksum[0], cksum[1], cksum[0]); + return; + } + if (eh->version != 1) { + printf(" unsupported version %d", eh->version); + return; + } + p += sizeof(*eh) + 2; + li -= sizeof(*eh) + 2; /* protoid * li */ + + switch (eh->type & 0x1f) { + case ESIS_REDIRECT: { + const u_char *dst, *snpa, *is; + + dst = p; p += *p + 1; + if (p > snapend) + return; + printf(" %s", isonsap_string(dst)); + snpa = p; p += *p + 1; + is = p; p += *p + 1; + if (p > snapend) + return; + if (p > ep) { + printf(" [bad li]"); + return; + } + if (is[0] == 0) + printf(" > %s", etheraddr_string(&snpa[1])); + else + printf(" > %s", isonsap_string(is)); + li = ep - p; + break; + } +#if 0 + case ESIS_ESH: + printf(" esh"); + break; +#endif + case ESIS_ISH: { + const u_char *is; + + is = p; p += *p + 1; + if (p > ep) { + printf(" [bad li]"); + return; + } + if (p > snapend) + return; + printf(" %s", isonsap_string(is)); + li = ep - p; + break; + } + + default: + (void)printf(" len=%d", length); + if (length && p < snapend) { + length = snapend - p; + default_print(p, length); + } + return; + } + if (vflag) + while (p < ep && li) { + int op, opli; + const u_char *q; + + if (snapend - p < 2) + return; + if (li < 2) { + printf(" bad opts/li"); + return; + } + op = *p++; + opli = *p++; + li -= 2; + if (opli > li) { + printf(" opt (%d) too long", op); + return; + } + li -= opli; + q = p; + p += opli; + if (snapend < p) + return; + if (op == 198 && opli == 2) { + printf(" tmo=%d", q[0] * 256 + q[1]); + continue; + } + printf (" %d:<", op); + while (--opli >= 0) + printf("%02x", *q++); + printf (">"); + } +} + +static int +osi_cksum(register const u_char *p, register u_int len, + const u_char *toff, u_char *cksum, u_char *off) +{ + int x, y, f = (len - ((toff - p) + 1)); + int32_t c0 = 0, c1 = 0; + + if ((cksum[0] = off[0]) == 0 && (cksum[1] = off[1]) == 0) + return 0; + + off[0] = off[1] = 0; + while (--len >= 0) { + c0 += *p++; + c1 += c0; + c0 %= 255; + c1 %= 255; + } + x = (c0 * f - c1); + if (x < 0) + x = 255 - (-x % 255); + else + x %= 255; + y = -1 * (x + c0); + if (y < 0) + y = 255 - (-y % 255); + else + y %= 255; + + off[0] = x; + off[1] = y; + + return (off[0] != cksum[0] || off[1] != cksum[1]); +} diff --git a/tcpdump.tproj/print-krb.c b/tcpdump.tproj/print-krb.c new file mode 100644 index 0000000..16116a0 --- /dev/null +++ b/tcpdump.tproj/print-krb.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Initial contribution from John Hawkinson (jhawk@mit.edu). + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-krb.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +const u_char *c_print(register const u_char *, register const u_char *); +const u_char *krb4_print_hdr(const u_char *); +void krb4_print(const u_char *); +void krb_print(const u_char *, u_int); + + +#define AUTH_MSG_KDC_REQUEST 1<<1 +#define AUTH_MSG_KDC_REPLY 2<<1 +#define AUTH_MSG_APPL_REQUEST 3<<1 +#define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1 +#define AUTH_MSG_ERR_REPLY 5<<1 +#define AUTH_MSG_PRIVATE 6<<1 +#define AUTH_MSG_SAFE 7<<1 +#define AUTH_MSG_APPL_ERR 8<<1 +#define AUTH_MSG_DIE 63<<1 + +#define KERB_ERR_OK 0 +#define KERB_ERR_NAME_EXP 1 +#define KERB_ERR_SERVICE_EXP 2 +#define KERB_ERR_AUTH_EXP 3 +#define KERB_ERR_PKT_VER 4 +#define KERB_ERR_NAME_MAST_KEY_VER 5 +#define KERB_ERR_SERV_MAST_KEY_VER 6 +#define KERB_ERR_BYTE_ORDER 7 +#define KERB_ERR_PRINCIPAL_UNKNOWN 8 +#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 +#define KERB_ERR_NULL_KEY 10 + +struct krb { + u_char pvno; /* Protocol Version */ + u_char type; /* Type+B */ +}; + +static char tstr[] = " [|kerberos]"; + +static struct tok type2str[] = { + { AUTH_MSG_KDC_REQUEST, "KDC_REQUEST" }, + { AUTH_MSG_KDC_REPLY, "KDC_REPLY" }, + { AUTH_MSG_APPL_REQUEST, "APPL_REQUEST" }, + { AUTH_MSG_APPL_REQUEST_MUTUAL, "APPL_REQUEST_MUTUAL" }, + { AUTH_MSG_ERR_REPLY, "ERR_REPLY" }, + { AUTH_MSG_PRIVATE, "PRIVATE" }, + { AUTH_MSG_SAFE, "SAFE" }, + { AUTH_MSG_APPL_ERR, "APPL_ERR" }, + { AUTH_MSG_DIE, "DIE" }, + { 0, NULL } +}; + +static struct tok kerr2str[] = { + { KERB_ERR_OK, "OK" }, + { KERB_ERR_NAME_EXP, "NAME_EXP" }, + { KERB_ERR_SERVICE_EXP, "SERVICE_EXP" }, + { KERB_ERR_AUTH_EXP, "AUTH_EXP" }, + { KERB_ERR_PKT_VER, "PKT_VER" }, + { KERB_ERR_NAME_MAST_KEY_VER, "NAME_MAST_KEY_VER" }, + { KERB_ERR_SERV_MAST_KEY_VER, "SERV_MAST_KEY_VER" }, + { KERB_ERR_BYTE_ORDER, "BYTE_ORDER" }, + { KERB_ERR_PRINCIPAL_UNKNOWN, "PRINCIPAL_UNKNOWN" }, + { KERB_ERR_PRINCIPAL_NOT_UNIQUE, "PRINCIPAL_NOT_UNIQUE" }, + { KERB_ERR_NULL_KEY, "NULL_KEY"}, + { 0, NULL} +}; + + +/* little endian (unaligned) to host byte order */ +/* XXX need to look at this... */ +#define vtohlp(x) ((( ((char *)(x))[0] ) ) | \ + (( ((char *)(x))[1] ) << 8) | \ + (( ((char *)(x))[2] ) << 16) | \ + (( ((char *)(x))[3] ) << 24)) +#define vtohsp(x) ((( ((char *)(x))[0] ) ) | \ + (( ((char *)(x))[1] ) << 8)) +/* network (big endian) (unaligned) to host byte order */ +#define ntohlp(x) ((( ((char *)(x))[3] ) ) | \ + (( ((char *)(x))[2] ) << 8) | \ + (( ((char *)(x))[1] ) << 16) | \ + (( ((char *)(x))[0] ) << 24)) +#define ntohsp(x) ((( ((char *)(x))[1] ) ) | \ + (( ((char *)(x))[0] ) << 8)) + + + +const u_char * +c_print(register const u_char *s, register const u_char *ep) +{ + register u_char c; + register int flag; + + flag = 1; + while (ep == NULL || s < ep) { + c = *s++; + if (c == '\0') { + flag = 0; + break; + } + if (!isascii(c)) { + c = toascii(c); + putchar('M'); + putchar('-'); + } + if (!isprint(c)) { + c ^= 0x40; /* DEL to ?, others to alpha */ + putchar('^'); + } + putchar(c); + } + if (flag) + return NULL; + return(s); +} + +const u_char * +krb4_print_hdr(const u_char *cp) +{ + cp+=2; + +#define PRINT if ((cp=c_print(cp, snapend))==NULL) goto trunc + + TCHECK2(cp, 0); + PRINT; + TCHECK2(cp, 0); + putchar('.'); PRINT; + TCHECK2(cp, 0); + putchar('@'); PRINT; + return(cp); + +trunc: + fputs(tstr, stdout); + return(NULL); + +#undef PRINT +} + +void +krb4_print(const u_char *cp) +{ + register const struct krb *kp; + u_char type; + u_short len; + +#define PRINT if ((cp=c_print(cp, snapend))==NULL) goto trunc +/* True if struct krb is little endian */ +#define IS_LENDIAN(kp) (((kp)->type & 0x01) != 0) +#define KTOHSP(kp, cp) (IS_LENDIAN(kp) ? vtohsp(cp) : ntohsp(cp)) + + kp = (struct krb *)cp; + + if ((&kp->type) >= snapend) { + fputs(tstr, stdout); + return; + } + + type = kp->type & (0xFF << 1); + + printf(" %s %s: ", + IS_LENDIAN(kp) ? "le" : "be", tok2str(type2str, NULL, type)); + + switch (type) { + + case AUTH_MSG_KDC_REQUEST: + if ((cp = krb4_print_hdr(cp)) == NULL) + return; + cp += 4; /* ctime */ + TCHECK2(cp, 0); + printf(" %dmin ", *cp++ * 5); + TCHECK2(cp, 0); + PRINT; + TCHECK2(cp, 0); + putchar('.'); PRINT; + break; + + case AUTH_MSG_APPL_REQUEST: + cp += 2; + TCHECK2(cp, 0); + printf("v%d ", *cp++); + TCHECK2(cp, 0); + PRINT; + TCHECK2(cp, 0); + printf(" (%d)", *cp++); + TCHECK2(cp, 0); + printf(" (%d)", *cp); + TCHECK2(cp, 0); + break; + + case AUTH_MSG_KDC_REPLY: + if ((cp = krb4_print_hdr(cp)) == NULL) + return; + cp += 10; /* timestamp + n + exp + kvno */ + TCHECK2(cp, 0); + len = KTOHSP(kp, cp); + printf(" (%d)", len); + TCHECK2(cp, 0); + break; + + case AUTH_MSG_ERR_REPLY: + if ((cp = krb4_print_hdr(cp)) == NULL) + return; + cp += 4; /* timestamp */ + TCHECK2(cp, 0); + printf(" %s ", tok2str(kerr2str, NULL, KTOHSP(kp, cp))); + cp += 4; + TCHECK2(cp, 0); + PRINT; + break; + + default: + fputs("(unknown)", stdout); + break; + } + + return; +trunc: + fputs(tstr, stdout); +} + +void +krb_print(const u_char *dat, u_int length) +{ + register const struct krb *kp; + + kp = (struct krb *)dat; + + if (dat >= snapend) { + fputs(tstr, stdout); + return; + } + + switch (kp->pvno) { + + case 1: + case 2: + case 3: + printf(" v%d", kp->pvno); + break; + + case 4: + printf(" v%d", kp->pvno); + krb4_print((const u_char *)kp); + break; + + case 106: + case 107: + fputs(" v5", stdout); + /* Decode ASN.1 here "someday" */ + break; + } + return; +} diff --git a/tcpdump.tproj/print-llc.c b/tcpdump.tproj/print-llc.c new file mode 100644 index 0000000..4deb6ed --- /dev/null +++ b/tcpdump.tproj/print-llc.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Code by Matt Thomas, Digital Equipment Corporation + * with an awful lot of hacking by Jeffrey Mogul, DECWRL + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-llc.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $"; +#endif + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +#include "llc.h" + +static struct tok cmd2str[] = { + { LLC_UI, "ui" }, + { LLC_TEST, "test" }, + { LLC_XID, "xid" }, + { LLC_UA, "ua" }, + { LLC_DISC, "disc" }, + { LLC_DM, "dm" }, + { LLC_SABME, "sabme" }, + { LLC_FRMR, "frmr" }, + { 0, NULL } +}; + +/* + * Returns non-zero IFF it succeeds in printing the header + */ +int +llc_print(const u_char *p, u_int length, u_int caplen, + const u_char *esrc, const u_char *edst) +{ + struct llc llc; + register u_short et; + register int ret; + + if (caplen < 3) { + (void)printf("[|llc]"); + default_print((u_char *)p, caplen); + return(0); + } + + /* Watch out for possible alignment problems */ + memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc))); + + if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) { + ipx_print(p, length); + return (1); + } +#ifdef notyet + else if (p[0] == 0xf0 && p[1] == 0xf0) + netbios_print(p, length); +#endif + if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS + && llc.llcui == LLC_UI) { + isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst); + return (1); + } + + if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP + && llc.llcui == LLC_UI) { + if (caplen < sizeof(llc)) { + (void)printf("[|llc-snap]"); + default_print((u_char *)p, caplen); + return (0); + } + if (vflag) + (void)printf("snap %s ", protoid_string(llc.llcpi)); + + caplen -= sizeof(llc); + length -= sizeof(llc); + p += sizeof(llc); + + /* This is an encapsulated Ethernet packet */ + et = EXTRACT_16BITS(&llc.ethertype[0]); + ret = ether_encap_print(et, p, length, caplen); + if (ret) + return (ret); + } + + if ((llc.ssap & ~LLC_GSAP) == llc.dsap) { + if (eflag) + (void)printf("%s ", llcsap_string(llc.dsap)); + else + (void)printf("%s > %s %s ", + etheraddr_string(esrc), + etheraddr_string(edst), + llcsap_string(llc.dsap)); + } else { + if (eflag) + (void)printf("%s > %s ", + llcsap_string(llc.ssap & ~LLC_GSAP), + llcsap_string(llc.dsap)); + else + (void)printf("%s %s > %s %s ", + etheraddr_string(esrc), + llcsap_string(llc.ssap & ~LLC_GSAP), + etheraddr_string(edst), + llcsap_string(llc.dsap)); + } + + if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) { + const char *m; + char f; + m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu)); + switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { + case 0: f = 'C'; break; + case LLC_GSAP: f = 'R'; break; + case LLC_U_POLL: f = 'P'; break; + case LLC_GSAP|LLC_U_POLL: f = 'F'; break; + default: f = '?'; break; + } + + printf("%s/%c", m, f); + + p += 3; + length -= 3; + caplen -= 3; + + if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) { + if (*p == LLC_XID_FI) { + printf(": %02x %02x", p[1], p[2]); + p += 3; + length -= 3; + caplen -= 3; + } + } + } else { + char f; + llc.llcis = ntohs(llc.llcis); + switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) { + case 0: f = 'C'; break; + case LLC_GSAP: f = 'R'; break; + case LLC_U_POLL: f = 'P'; break; + case LLC_GSAP|LLC_U_POLL: f = 'F'; break; + default: f = '?'; break; + } + + if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) { + static char *llc_s[] = { "rr", "rej", "rnr", "03" }; + (void)printf("%s (r=%d,%c)", + llc_s[LLC_S_CMD(llc.llcis)], + LLC_IS_NR(llc.llcis), + f); + } else { + (void)printf("I (s=%d,r=%d,%c)", + LLC_I_NS(llc.llcis), + LLC_IS_NR(llc.llcis), + f); + } + p += 4; + length -= 4; + caplen -= 4; + } + (void)printf(" len=%d", length); + if (caplen > 0) { + default_print_unaligned(p, caplen); + } + return(1); +} diff --git a/tcpdump.tproj/print-netbios.c b/tcpdump.tproj/print-netbios.c new file mode 100644 index 0000000..fdf16a3 --- /dev/null +++ b/tcpdump.tproj/print-netbios.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print NETBIOS packets. + * Contributed by Brad Parker (brad@fcr.com). + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-netbios.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $"; +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __STDC__ +#include +#endif +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "netbios.h" +#include "extract.h" + +/* + * Print NETBIOS packets. + */ +void +netbios_print(struct p8022Hdr *nb, u_int length) +{ + if (length < p8022Size) { + (void)printf(" truncated-netbios %d", length); + return; + } + + if (nb->flags == UI) { + (void)printf("802.1 UI "); + } else { + (void)printf("802.1 CONN "); + } + + if ((u_char *)(nb + 1) > snapend) { + printf(" [|netbios]"); + return; + } + +/* + netbios_decode(nb, (u_char *)nb + p8022Size, length - p8022Size); +*/ +} + +#ifdef never + (void)printf("%s.%d > ", + ipxaddr_string(EXTRACT_32BITS(ipx->srcNet), ipx->srcNode), + EXTRACT_16BITS(ipx->srcSkt)); + + (void)printf("%s.%d:", + ipxaddr_string(EXTRACT_32BITS(ipx->dstNet), ipx->dstNode), + EXTRACT_16BITS(ipx->dstSkt)); + + if ((u_char *)(ipx + 1) > snapend) { + printf(" [|ipx]"); + return; + } + + /* take length from ipx header */ + length = EXTRACT_16BITS(&ipx->length); + + ipx_decode(ipx, (u_char *)ipx + ipxSize, length - ipxSize); +#endif + diff --git a/tcpdump.tproj/print-nfs.c b/tcpdump.tproj/print-nfs.c new file mode 100644 index 0000000..9f7b5b2 --- /dev/null +++ b/tcpdump.tproj/print-nfs.c @@ -0,0 +1,891 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-nfs.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +#include "nfsv2.h" +#include "nfsfh.h" + +static void nfs_printfh(const u_int32_t *); +static void xid_map_enter(const struct rpc_msg *, const struct ip *); +static int32_t xid_map_find(const struct rpc_msg *, const struct ip *); +static void interp_reply(const struct rpc_msg *, u_int32_t, u_int); + +static int nfserr; /* true if we error rather than trunc */ + +void +nfsreply_print(register const u_char *bp, u_int length, + register const u_char *bp2) +{ + register const struct rpc_msg *rp; + register const struct ip *ip; + int32_t proc; + + nfserr = 0; /* assume no error */ + rp = (const struct rpc_msg *)bp; + ip = (const struct ip *)bp2; + + if (!nflag) + (void)printf("%s.nfs > %s.%x: reply %s %d", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst), + (u_int32_t)ntohl(rp->rm_xid), + ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? + "ok":"ERR", + length); + else + (void)printf("%s.%x > %s.%x: reply %s %d", + ipaddr_string(&ip->ip_src), + NFS_PORT, + ipaddr_string(&ip->ip_dst), + (u_int32_t)ntohl(rp->rm_xid), + ntohl(rp->rm_reply.rp_stat) == MSG_ACCEPTED? + "ok":"ERR", + length); + + proc = xid_map_find(rp, ip); + if (proc >= 0) + interp_reply(rp, (u_int32_t)proc, length); +} + +/* + * Return a pointer to the first file handle in the packet. + * If the packet was truncated, return 0. + */ +static const u_int32_t * +parsereq(register const struct rpc_msg *rp, register u_int length) +{ + register const u_int32_t *dp; + register u_int len; + + /* + * find the start of the req data (if we captured it) + */ + dp = (u_int32_t *)&rp->rm_call.cb_cred; + TCHECK(dp[1]); + len = ntohl(dp[1]); + if (len < length) { + dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); + TCHECK(dp[1]); + len = ntohl(dp[1]); + if (len < length) { + dp += (len + (2 * sizeof(*dp) + 3)) / sizeof(*dp); + TCHECK2(dp[0], 0); + return (dp); + } + } +trunc: + return (NULL); +} + +/* + * Print out an NFS file handle and return a pointer to following word. + * If packet was truncated, return 0. + */ +static const u_int32_t * +parsefh(register const u_int32_t *dp) +{ + if (dp + 8 <= (u_int32_t *)snapend) { + nfs_printfh(dp); + return (dp + 8); + } + return (NULL); +} + +/* + * Print out a file name and return pointer to 32-bit word past it. + * If packet was truncated, return 0. + */ +static const u_int32_t * +parsefn(register const u_int32_t *dp) +{ + register u_int32_t len; + register const u_char *cp; + + /* Bail if we don't have the string length */ + if ((u_char *)dp > snapend - sizeof(*dp)) + return (NULL); + + /* Fetch string length; convert to host order */ + len = *dp++; + NTOHL(len); + + cp = (u_char *)dp; + /* Update 32-bit pointer (NFS filenames padded to 32-bit boundaries) */ + dp += ((len + 3) & ~3) / sizeof(*dp); + if ((u_char *)dp > snapend) + return (NULL); + /* XXX seems like we should be checking the length */ + putchar('"'); + (void) fn_printn(cp, len, NULL); + putchar('"'); + + return (dp); +} + +/* + * Print out file handle and file name. + * Return pointer to 32-bit word past file name. + * If packet was truncated (or there was some other error), return 0. + */ +static const u_int32_t * +parsefhn(register const u_int32_t *dp) +{ + dp = parsefh(dp); + if (dp == NULL) + return (NULL); + putchar(' '); + return (parsefn(dp)); +} + +void +nfsreq_print(register const u_char *bp, u_int length, + register const u_char *bp2) +{ + register const struct rpc_msg *rp; + register const struct ip *ip; + register const u_int32_t *dp; + + nfserr = 0; /* assume no error */ + rp = (const struct rpc_msg *)bp; + ip = (const struct ip *)bp2; + if (!nflag) + (void)printf("%s.%x > %s.nfs: %d", + ipaddr_string(&ip->ip_src), + (u_int32_t)ntohl(rp->rm_xid), + ipaddr_string(&ip->ip_dst), + length); + else + (void)printf("%s.%x > %s.%x: %d", + ipaddr_string(&ip->ip_src), + (u_int32_t)ntohl(rp->rm_xid), + ipaddr_string(&ip->ip_dst), + NFS_PORT, + length); + + xid_map_enter(rp, ip); /* record proc number for later on */ + + switch (ntohl(rp->rm_call.cb_proc)) { +#ifdef NFSPROC_NOOP + case NFSPROC_NOOP: + printf(" nop"); + return; +#else +#define NFSPROC_NOOP -1 +#endif + case NFSPROC_NULL: + printf(" null"); + return; + + case NFSPROC_GETATTR: + printf(" getattr"); + if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL) + return; + break; + + case NFSPROC_SETATTR: + printf(" setattr"); + if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL) + return; + break; + +#if NFSPROC_ROOT != NFSPROC_NOOP + case NFSPROC_ROOT: + printf(" root"); + break; +#endif + case NFSPROC_LOOKUP: + printf(" lookup"); + if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL) + return; + break; + + case NFSPROC_READLINK: + printf(" readlink"); + if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL) + return; + break; + + case NFSPROC_READ: + printf(" read"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefh(dp)) != NULL) { + TCHECK2(dp[0], 3 * sizeof(*dp)); + printf(" %u bytes @ %u", + (u_int32_t)ntohl(dp[1]), + (u_int32_t)ntohl(dp[0])); + return; + } + break; + +#if NFSPROC_WRITECACHE != NFSPROC_NOOP + case NFSPROC_WRITECACHE: + printf(" writecache"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefh(dp)) != NULL) { + TCHECK2(dp[0], 4 * sizeof(*dp)); + printf(" %u (%u) bytes @ %u (%u)", + (u_int32_t)ntohl(dp[3]), + (u_int32_t)ntohl(dp[2]), + (u_int32_t)ntohl(dp[1]), + (u_int32_t)ntohl(dp[0])); + return; + } + break; +#endif + case NFSPROC_WRITE: + printf(" write"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefh(dp)) != NULL) { + TCHECK2(dp[0], 4 * sizeof(*dp)); + printf(" %u (%u) bytes @ %u (%u)", + (u_int32_t)ntohl(dp[3]), + (u_int32_t)ntohl(dp[2]), + (u_int32_t)ntohl(dp[1]), + (u_int32_t)ntohl(dp[0])); + return; + } + break; + + case NFSPROC_CREATE: + printf(" create"); + if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL) + return; + break; + + case NFSPROC_REMOVE: + printf(" remove"); + if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL) + return; + break; + + case NFSPROC_RENAME: + printf(" rename"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefhn(dp)) != NULL) { + fputs(" ->", stdout); + if (parsefhn(dp) != NULL) + return; + } + break; + + case NFSPROC_LINK: + printf(" link"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefh(dp)) != NULL) { + fputs(" ->", stdout); + if (parsefhn(dp) != NULL) + return; + } + break; + + case NFSPROC_SYMLINK: + printf(" symlink"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefhn(dp)) != NULL) { + fputs(" -> ", stdout); + if (parsefn(dp) != NULL) + return; + } + break; + + case NFSPROC_MKDIR: + printf(" mkdir"); + if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL) + return; + break; + + case NFSPROC_RMDIR: + printf(" rmdir"); + if ((dp = parsereq(rp, length)) != NULL && parsefhn(dp) != NULL) + return; + break; + + case NFSPROC_READDIR: + printf(" readdir"); + if ((dp = parsereq(rp, length)) != NULL && + (dp = parsefh(dp)) != NULL) { + TCHECK2(dp[0], 2 * sizeof(*dp)); + /* + * Print the offset as signed, since -1 is common, + * but offsets > 2^31 aren't. + */ + printf(" %u bytes @ %d", + (u_int32_t)ntohl(dp[1]), + (u_int32_t)ntohl(dp[0])); + return; + } + break; + + case NFSPROC_STATFS: + printf(" statfs"); + if ((dp = parsereq(rp, length)) != NULL && parsefh(dp) != NULL) + return; + break; + + default: + printf(" proc-%u", (u_int32_t)ntohl(rp->rm_call.cb_proc)); + return; + } +trunc: + if (!nfserr) + fputs(" [|nfs]", stdout); +} + +/* + * Print out an NFS file handle. + * We assume packet was not truncated before the end of the + * file handle pointed to by dp. + * + * Note: new version (using portable file-handle parser) doesn't produce + * generation number. It probably could be made to do that, with some + * additional hacking on the parser code. + */ +static void +nfs_printfh(register const u_int32_t *dp) +{ + my_fsid fsid; + ino_t ino; + char *sfsname = NULL; + + Parse_fh((caddr_t *)dp, &fsid, &ino, NULL, &sfsname, 0); + + if (sfsname) { + /* file system ID is ASCII, not numeric, for this server OS */ + static char temp[NFS_FHSIZE+1]; + + /* Make sure string is null-terminated */ + strncpy(temp, sfsname, NFS_FHSIZE); + /* Remove trailing spaces */ + sfsname = strchr(temp, ' '); + if (sfsname) + *sfsname = 0; + + (void)printf(" fh %s/%u", temp, (u_int32_t)ino); + } else { + (void)printf(" fh %u,%u/%u", + fsid.Fsid_dev.Major, fsid.Fsid_dev.Minor, (u_int32_t)ino); + } +} + +/* + * Maintain a small cache of recent client.XID.server/proc pairs, to allow + * us to match up replies with requests and thus to know how to parse + * the reply. + */ + +struct xid_map_entry { + u_int32_t xid; /* transaction ID (net order) */ + struct in_addr client; /* client IP address (net order) */ + struct in_addr server; /* server IP address (net order) */ + u_int32_t proc; /* call proc number (host order) */ +}; + +/* + * Map entries are kept in an array that we manage as a ring; + * new entries are always added at the tail of the ring. Initially, + * all the entries are zero and hence don't match anything. + */ + +#define XIDMAPSIZE 64 + +struct xid_map_entry xid_map[XIDMAPSIZE]; + +int xid_map_next = 0; +int xid_map_hint = 0; + +static void +xid_map_enter(const struct rpc_msg *rp, const struct ip *ip) +{ + struct xid_map_entry *xmep; + + xmep = &xid_map[xid_map_next]; + + if (++xid_map_next >= XIDMAPSIZE) + xid_map_next = 0; + + xmep->xid = rp->rm_xid; + xmep->client = ip->ip_src; + xmep->server = ip->ip_dst; + xmep->proc = ntohl(rp->rm_call.cb_proc); +} + +/* Returns NFSPROC_xxx or -1 on failure */ +static int32_t +xid_map_find(const struct rpc_msg *rp, const struct ip *ip) +{ + int i; + struct xid_map_entry *xmep; + u_int32_t xid = rp->rm_xid; + u_int32_t clip = ip->ip_dst.s_addr; + u_int32_t sip = ip->ip_src.s_addr; + + /* Start searching from where we last left off */ + i = xid_map_hint; + do { + xmep = &xid_map[i]; + if (xmep->xid == xid && xmep->client.s_addr == clip && + xmep->server.s_addr == sip) { + /* match */ + xid_map_hint = i; + return ((int32_t)xmep->proc); + } + if (++i >= XIDMAPSIZE) + i = 0; + } while (i != xid_map_hint); + + /* search failed */ + return (-1); +} + +/* + * Routines for parsing reply packets + */ + +/* + * Return a pointer to the beginning of the actual results. + * If the packet was truncated, return 0. + */ +static const u_int32_t * +parserep(register const struct rpc_msg *rp, register u_int length) +{ + register const u_int32_t *dp; + u_int len; + enum accept_stat astat; + + /* + * Portability note: + * Here we find the address of the ar_verf credentials. + * Originally, this calculation was + * dp = (u_int32_t *)&rp->rm_reply.rp_acpt.ar_verf + * On the wire, the rp_acpt field starts immediately after + * the (32 bit) rp_stat field. However, rp_acpt (which is a + * "struct accepted_reply") contains a "struct opaque_auth", + * whose internal representation contains a pointer, so on a + * 64-bit machine the compiler inserts 32 bits of padding + * before rp->rm_reply.rp_acpt.ar_verf. So, we cannot use + * the internal representation to parse the on-the-wire + * representation. Instead, we skip past the rp_stat field, + * which is an "enum" and so occupies one 32-bit word. + */ + dp = ((const u_int32_t *)&rp->rm_reply) + 1; + TCHECK2(dp[0], 1); + len = ntohl(dp[1]); + if (len >= length) + return (NULL); + /* + * skip past the ar_verf credentials. + */ + dp += (len + (2*sizeof(u_int32_t) + 3)) / sizeof(u_int32_t); + TCHECK2(dp[0], 0); + + /* + * now we can check the ar_stat field + */ + astat = ntohl(*(enum accept_stat *)dp); + switch (astat) { + + case SUCCESS: + break; + + case PROG_UNAVAIL: + printf(" PROG_UNAVAIL"); + nfserr = 1; /* suppress trunc string */ + return (NULL); + + case PROG_MISMATCH: + printf(" PROG_MISMATCH"); + nfserr = 1; /* suppress trunc string */ + return (NULL); + + case PROC_UNAVAIL: + printf(" PROC_UNAVAIL"); + nfserr = 1; /* suppress trunc string */ + return (NULL); + + case GARBAGE_ARGS: + printf(" GARBAGE_ARGS"); + nfserr = 1; /* suppress trunc string */ + return (NULL); + + case SYSTEM_ERR: + printf(" SYSTEM_ERR"); + nfserr = 1; /* suppress trunc string */ + return (NULL); + + default: + printf(" ar_stat %d", astat); + nfserr = 1; /* suppress trunc string */ + return (NULL); + } + /* successful return */ + if ((sizeof(astat) + ((u_char *)dp)) < snapend) + return ((u_int32_t *) (sizeof(astat) + ((char *)dp))); + +trunc: + return (NULL); +} + +static const u_int32_t * +parsestatus(const u_int32_t *dp) +{ + register int errnum; + + TCHECK(dp[0]); + errnum = ntohl(dp[0]); + if (errnum != 0) { + if (!qflag) + printf(" ERROR: %s", pcap_strerror(errnum)); + nfserr = 1; /* suppress trunc string */ + return (NULL); + } + return (dp + 1); +trunc: + return (NULL); +} + +static struct tok type2str[] = { + { NFNON, "NON" }, + { NFREG, "REG" }, + { NFDIR, "DIR" }, + { NFBLK, "BLK" }, + { NFCHR, "CHR" }, + { NFLNK, "LNK" }, + { 0, NULL } +}; + +static const u_int32_t * +parsefattr(const u_int32_t *dp, int verbose) +{ + const struct nfsv2_fattr *fap; + + fap = (const struct nfsv2_fattr *)dp; + if (verbose) { + TCHECK(fap->fa_nfssize); + printf(" %s %o ids %u/%u sz %u ", + tok2str(type2str, "unk-ft %d ", + (u_int32_t)ntohl(fap->fa_type)), + (u_int32_t)ntohl(fap->fa_mode), + (u_int32_t)ntohl(fap->fa_uid), + (u_int32_t)ntohl(fap->fa_gid), + (u_int32_t)ntohl(fap->fa_nfssize)); + } + /* print lots more stuff */ + if (verbose > 1) { + TCHECK(fap->fa_nfsfileid); + printf("nlink %u rdev %x fsid %x nodeid %x a/m/ctime ", + (u_int32_t)ntohl(fap->fa_nlink), + (u_int32_t)ntohl(fap->fa_nfsrdev), + (u_int32_t)ntohl(fap->fa_nfsfsid), + (u_int32_t)ntohl(fap->fa_nfsfileid)); + TCHECK(fap->fa_nfsatime); + printf("%u.%06u ", + (u_int32_t)ntohl(fap->fa_nfsatime.nfs_sec), + (u_int32_t)ntohl(fap->fa_nfsatime.nfs_usec)); + TCHECK(fap->fa_nfsmtime); + printf("%u.%06u ", + (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_sec), + (u_int32_t)ntohl(fap->fa_nfsmtime.nfs_usec)); + TCHECK(fap->fa_nfsctime); + printf("%u.%06u ", + (u_int32_t)ntohl(fap->fa_nfsctime.nfs_sec), + (u_int32_t)ntohl(fap->fa_nfsctime.nfs_usec)); + } + return ((const u_int32_t *)&fap[1]); +trunc: + return (NULL); +} + +static int +parseattrstat(const u_int32_t *dp, int verbose) +{ + + dp = parsestatus(dp); + if (dp == NULL) + return (0); + + return (parsefattr(dp, verbose) != NULL); +} + +static int +parsediropres(const u_int32_t *dp) +{ + + dp = parsestatus(dp); + if (dp == NULL) + return (0); + + dp = parsefh(dp); + if (dp == NULL) + return (0); + + return (parsefattr(dp, vflag) != NULL); +} + +static int +parselinkres(const u_int32_t *dp) +{ + dp = parsestatus(dp); + if (dp == NULL) + return (0); + + putchar(' '); + return (parsefn(dp) != NULL); +} + +static int +parsestatfs(const u_int32_t *dp) +{ + const struct nfsv2_statfs *sfsp; + + dp = parsestatus(dp); + if (dp == NULL) + return (0); + + if (!qflag) { + sfsp = (const struct nfsv2_statfs *)dp; + TCHECK(sfsp->sf_bavail); + printf(" tsize %u bsize %u blocks %u bfree %u bavail %u", + (u_int32_t)ntohl(sfsp->sf_tsize), + (u_int32_t)ntohl(sfsp->sf_bsize), + (u_int32_t)ntohl(sfsp->sf_blocks), + (u_int32_t)ntohl(sfsp->sf_bfree), + (u_int32_t)ntohl(sfsp->sf_bavail)); + } + + return (1); +trunc: + return (0); +} + +static int +parserddires(const u_int32_t *dp) +{ + dp = parsestatus(dp); + if (dp == NULL) + return (0); + if (!qflag) { + TCHECK(dp[0]); + printf(" offset %x", (u_int32_t)ntohl(dp[0])); + TCHECK(dp[1]); + printf(" size %u", (u_int32_t)ntohl(dp[1])); + TCHECK(dp[2]); + if (dp[2] != 0) + printf(" eof"); + } + + return (1); +trunc: + return (0); +} + +static void +interp_reply(const struct rpc_msg *rp, u_int32_t proc, u_int length) +{ + register const u_int32_t *dp; + + switch (proc) { + +#ifdef NFSPROC_NOOP + case NFSPROC_NOOP: + printf(" nop"); + return; +#else +#define NFSPROC_NOOP -1 +#endif + case NFSPROC_NULL: + printf(" null"); + return; + + case NFSPROC_GETATTR: + printf(" getattr"); + dp = parserep(rp, length); + if (dp != NULL && parseattrstat(dp, !qflag) != 0) + return; + break; + + case NFSPROC_SETATTR: + printf(" setattr"); + dp = parserep(rp, length); + if (dp != NULL && parseattrstat(dp, !qflag) != 0) + return; + break; + +#if NFSPROC_ROOT != NFSPROC_NOOP + case NFSPROC_ROOT: + printf(" root"); + break; +#endif + case NFSPROC_LOOKUP: + printf(" lookup"); + dp = parserep(rp, length); + if (dp != NULL && parsediropres(dp) != 0) + return; + break; + + case NFSPROC_READLINK: + printf(" readlink"); + dp = parserep(rp, length); + if (dp != NULL && parselinkres(dp) != 0) + return; + break; + + case NFSPROC_READ: + printf(" read"); + dp = parserep(rp, length); + if (dp != NULL && parseattrstat(dp, vflag) != 0) + return; + break; + +#if NFSPROC_WRITECACHE != NFSPROC_NOOP + case NFSPROC_WRITECACHE: + printf(" writecache"); + break; +#endif + case NFSPROC_WRITE: + printf(" write"); + dp = parserep(rp, length); + if (dp != NULL && parseattrstat(dp, vflag) != 0) + return; + break; + + case NFSPROC_CREATE: + printf(" create"); + dp = parserep(rp, length); + if (dp != NULL && parsediropres(dp) != 0) + return; + break; + + case NFSPROC_REMOVE: + printf(" remove"); + dp = parserep(rp, length); + if (dp != NULL && parsestatus(dp) != 0) + return; + break; + + case NFSPROC_RENAME: + printf(" rename"); + dp = parserep(rp, length); + if (dp != NULL && parsestatus(dp) != 0) + return; + break; + + case NFSPROC_LINK: + printf(" link"); + dp = parserep(rp, length); + if (dp != NULL && parsestatus(dp) != 0) + return; + break; + + case NFSPROC_SYMLINK: + printf(" symlink"); + dp = parserep(rp, length); + if (dp != NULL && parsestatus(dp) != 0) + return; + break; + + case NFSPROC_MKDIR: + printf(" mkdir"); + dp = parserep(rp, length); + if (dp != NULL && parsediropres(dp) != 0) + return; + break; + + case NFSPROC_RMDIR: + printf(" rmdir"); + dp = parserep(rp, length); + if (dp != NULL && parsestatus(dp) != 0) + return; + break; + + case NFSPROC_READDIR: + printf(" readdir"); + dp = parserep(rp, length); + if (dp != NULL && parserddires(dp) != 0) + return; + break; + + case NFSPROC_STATFS: + printf(" statfs"); + dp = parserep(rp, length); + if (dp != NULL && parsestatfs(dp) != 0) + return; + break; + + default: + printf(" proc-%u", proc); + return; + } + if (!nfserr) + fputs(" [|nfs]", stdout); +} diff --git a/tcpdump.tproj/print-ntp.c b/tcpdump.tproj/print-ntp.c new file mode 100644 index 0000000..52931a7 --- /dev/null +++ b/tcpdump.tproj/print-ntp.c @@ -0,0 +1,307 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print ntp packets. + * By Jeffrey Mogul/DECWRL + * loosely based on print-bootp.c + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ntp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#undef MODEMASK /* Solaris sucks */ +#include "ntp.h" + +static void p_sfix(const struct s_fixedpt *); +static void p_ntp_time(const struct l_fixedpt *); +static void p_ntp_delta(const struct l_fixedpt *, const struct l_fixedpt *); + +/* + * Print ntp requests + */ +void +ntp_print(register const u_char *cp, u_int length) +{ + register const struct ntpdata *bp; + int mode, version, leapind; + static char rclock[5]; + + bp = (struct ntpdata *)cp; + /* Note funny sized packets */ + if (length != sizeof(struct ntpdata)) + (void)printf(" [len=%d]", length); + + TCHECK(bp->status); + + version = (int)(bp->status & VERSIONMASK) >> 3; + printf(" v%d", version); + + leapind = bp->status & LEAPMASK; + switch (leapind) { + + case NO_WARNING: + break; + + case PLUS_SEC: + fputs(" +1s", stdout); + break; + + case MINUS_SEC: + fputs(" -1s", stdout); + break; + } + + mode = bp->status & MODEMASK; + switch (mode) { + + case MODE_UNSPEC: /* unspecified */ + fputs(" unspec", stdout); + break; + + case MODE_SYM_ACT: /* symmetric active */ + fputs(" sym_act", stdout); + break; + + case MODE_SYM_PAS: /* symmetric passive */ + fputs(" sym_pas", stdout); + break; + + case MODE_CLIENT: /* client */ + fputs(" client", stdout); + break; + + case MODE_SERVER: /* server */ + fputs(" server", stdout); + break; + + case MODE_BROADCAST: /* broadcast */ + fputs(" bcast", stdout); + break; + + case MODE_RES1: /* reserved */ + fputs(" res1", stdout); + break; + + case MODE_RES2: /* reserved */ + fputs(" res2", stdout); + break; + + } + + TCHECK(bp->stratum); + printf(" strat %d", bp->stratum); + + TCHECK(bp->ppoll); + printf(" poll %d", bp->ppoll); + + /* Can't TCHECK bp->precision bitfield so bp->distance + 0 instead */ + TCHECK2(bp->distance, 0); + printf(" prec %d", bp->precision); + + if (!vflag) + return; + + TCHECK(bp->distance); + fputs(" dist ", stdout); + p_sfix(&bp->distance); + + TCHECK(bp->dispersion); + fputs(" disp ", stdout); + p_sfix(&bp->dispersion); + + TCHECK(bp->refid); + fputs(" ref ", stdout); + /* Interpretation depends on stratum */ + switch (bp->stratum) { + + case UNSPECIFIED: + printf("(unspec)"); + break; + + case PRIM_REF: + strncpy(rclock, (char *)&(bp->refid), 4); + rclock[4] = '\0'; + fputs(rclock, stdout); + break; + + case INFO_QUERY: + printf("%s INFO_QUERY", ipaddr_string(&(bp->refid))); + /* this doesn't have more content */ + return; + + case INFO_REPLY: + printf("%s INFO_REPLY", ipaddr_string(&(bp->refid))); + /* this is too complex to be worth printing */ + return; + + default: + printf("%s", ipaddr_string(&(bp->refid))); + break; + } + + TCHECK(bp->reftime); + putchar('@'); + p_ntp_time(&(bp->reftime)); + + TCHECK(bp->org); + fputs(" orig ", stdout); + p_ntp_time(&(bp->org)); + + TCHECK(bp->rec); + fputs(" rec ", stdout); + p_ntp_delta(&(bp->org), &(bp->rec)); + + TCHECK(bp->xmt); + fputs(" xmt ", stdout); + p_ntp_delta(&(bp->org), &(bp->xmt)); + + return; + +trunc: + fputs(" [|ntp]", stdout); +} + +static void +p_sfix(register const struct s_fixedpt *sfp) +{ + register int i; + register int f; + register float ff; + + i = ntohs(sfp->int_part); + f = ntohs(sfp->fraction); + ff = f / 65536.0; /* shift radix point by 16 bits */ + f = ff * 1000000.0; /* Treat fraction as parts per million */ + printf("%d.%06d", i, f); +} + +#define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ + +static void +p_ntp_time(register const struct l_fixedpt *lfp) +{ + register int32_t i; + register u_int32_t uf; + register u_int32_t f; + register float ff; + + i = ntohl(lfp->int_part); + uf = ntohl(lfp->fraction); + ff = uf; + if (ff < 0.0) /* some compilers are buggy */ + ff += FMAXINT; + ff = ff / FMAXINT; /* shift radix point by 32 bits */ + f = ff * 1000000000.0; /* treat fraction as parts per billion */ + printf("%u.%09d", i, f); +} + +/* Prints time difference between *lfp and *olfp */ +static void +p_ntp_delta(register const struct l_fixedpt *olfp, + register const struct l_fixedpt *lfp) +{ + register int32_t i; + register u_int32_t uf; + register u_int32_t ouf; + register u_int32_t f; + register float ff; + int signbit; + + i = ntohl(lfp->int_part) - ntohl(olfp->int_part); + + uf = ntohl(lfp->fraction); + ouf = ntohl(olfp->fraction); + + if (i > 0) { /* new is definitely greater than old */ + signbit = 0; + f = uf - ouf; + if (ouf > uf) /* must borrow from high-order bits */ + i -= 1; + } else if (i < 0) { /* new is definitely less than old */ + signbit = 1; + f = ouf - uf; + if (uf > ouf) /* must carry into the high-order bits */ + i += 1; + i = -i; + } else { /* int_part is zero */ + if (uf > ouf) { + signbit = 0; + f = uf - ouf; + } else { + signbit = 1; + f = ouf - uf; + } + } + + ff = f; + if (ff < 0.0) /* some compilers are buggy */ + ff += FMAXINT; + ff = ff / FMAXINT; /* shift radix point by 32 bits */ + f = ff * 1000000000.0; /* treat fraction as parts per billion */ + if (signbit) + putchar('-'); + else + putchar('+'); + printf("%d.%09d", i, f); +} diff --git a/tcpdump.tproj/print-null.c b/tcpdump.tproj/print-null.c new file mode 100644 index 0000000..7dcf69b --- /dev/null +++ b/tcpdump.tproj/print-null.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-null.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "addrtoname.h" +#include "interface.h" + +#define NULL_HDRLEN 4 + +#ifndef AF_NS +#define AF_NS 6 /* XEROX NS protocols */ +#endif + +static void +null_print(const u_char *p, const struct ip *ip, u_int length) +{ + u_int family; + + memcpy((char *)&family, (char *)p, sizeof(family)); + + if (nflag) { + /* XXX just dump the header */ + return; + } + switch (family) { + + case AF_INET: + printf("ip: "); + break; + + case AF_NS: + printf("ns: "); + break; + + default: + printf("AF %d: ", family); + break; + } +} + +void +null_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + u_int length = h->len; + u_int caplen = h->caplen; + const struct ip *ip; + + ts_print(&h->ts); + + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = p; + snapend = p + caplen; + + length -= NULL_HDRLEN; + + ip = (struct ip *)(p + NULL_HDRLEN); + + if (eflag) + null_print(p, ip, length); + + ip_print((const u_char *)ip, length); + + if (xflag) + default_print((const u_char *)ip, caplen - NULL_HDRLEN); + putchar('\n'); +} + diff --git a/tcpdump.tproj/print-ospf.c b/tcpdump.tproj/print-ospf.c new file mode 100644 index 0000000..5012fb8 --- /dev/null +++ b/tcpdump.tproj/print-ospf.c @@ -0,0 +1,603 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ospf.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +#include "ospf.h" + +struct bits { + u_int32_t bit; + const char *str; +}; + +static const struct bits ospf_option_bits[] = { + { OSPF_OPTION_T, "T" }, + { OSPF_OPTION_E, "E" }, + { OSPF_OPTION_MC, "MC" }, + { 0, NULL } +}; + +static const struct bits ospf_rla_flag_bits[] = { + { RLA_FLAG_B, "B" }, + { RLA_FLAG_E, "E" }, + { RLA_FLAG_W1, "W1" }, + { RLA_FLAG_W2, "W2" }, + { 0, NULL } +}; + +static struct tok type2str[] = { + { OSPF_TYPE_UMD, "umd" }, + { OSPF_TYPE_HELLO, "hello" }, + { OSPF_TYPE_DB, "dd" }, + { OSPF_TYPE_LSR, "ls_req" }, + { OSPF_TYPE_LSU, "ls_upd" }, + { OSPF_TYPE_LSA, "ls_ack" }, + { 0, NULL } +}; + +static char tstr[] = " [|ospf]"; + +/* Forwards */ +static inline void ospf_print_seqage(u_int32_t, time_t); +static inline void ospf_print_bits(const struct bits *, u_char); +static void ospf_print_ls_type(u_int, const struct in_addr *, + const struct in_addr *, const char *); +static int ospf_print_lshdr(const struct lsa_hdr *); +static int ospf_print_lsa(const struct lsa *); +static int ospf_decode_v2(const struct ospfhdr *, const u_char *); + +static inline void +ospf_print_seqage(register u_int32_t seq, register time_t us) +{ + register time_t sec = us % 60; + register time_t mins = (us / 60) % 60; + register time_t hour = us / 3600; + + printf(" S %X age ", seq); + if (hour) + printf("%u:%02u:%02u", + (u_int32_t) hour, (u_int32_t) mins, (u_int32_t) sec); + else if (mins) + printf("%u:%02u", (u_int32_t) mins, (u_int32_t) sec); + else + printf("%u", (u_int32_t) sec); +} + + +static inline void +ospf_print_bits(register const struct bits *bp, register u_char options) +{ + register char sep = ' '; + + do { + if (options & bp->bit) { + printf("%c%s", sep, bp->str); + sep = '/'; + } + } while ((++bp)->bit); +} + +static void +ospf_print_ls_type(register u_int ls_type, + register const struct in_addr *ls_stateid, + register const struct in_addr *ls_router, register const char *fmt) +{ + + switch (ls_type) { + + case LS_TYPE_ROUTER: + printf(" rtr %s ", ipaddr_string(ls_router)); + break; + + case LS_TYPE_NETWORK: + printf(" net dr %s if %s", + ipaddr_string(ls_router), + ipaddr_string(ls_stateid)); + break; + + case LS_TYPE_SUM_IP: + printf(" sum %s abr %s", + ipaddr_string(ls_stateid), + ipaddr_string(ls_router)); + break; + + case LS_TYPE_SUM_ABR: + printf(" abr %s rtr %s", + ipaddr_string(ls_router), + ipaddr_string(ls_stateid)); + break; + + case LS_TYPE_ASE: + printf(" ase %s asbr %s", + ipaddr_string(ls_stateid), + ipaddr_string(ls_router)); + break; + + case LS_TYPE_GROUP: + printf(" group %s rtr %s", + ipaddr_string(ls_stateid), + ipaddr_string(ls_router)); + break; + + default: + putchar(' '); + printf(fmt, ls_type); + break; + } +} + +static int +ospf_print_lshdr(register const struct lsa_hdr *lshp) +{ + + TCHECK(lshp->ls_type); + printf(" {"); /* } (ctags) */ + + TCHECK(lshp->ls_options); + ospf_print_bits(ospf_option_bits, lshp->ls_options); + TCHECK(lshp->ls_seq); + ospf_print_seqage(ntohl(lshp->ls_seq), ntohs(lshp->ls_age)); + ospf_print_ls_type(lshp->ls_type, &lshp->ls_stateid, &lshp->ls_router, + "ls_type %d"); + + return (0); +trunc: + return (1); +} + + +/* + * Print a single link state advertisement. If truncated return 1, else 0. + */ +static int +ospf_print_lsa(register const struct lsa *lsap) +{ + register const u_char *ls_end; + register const struct rlalink *rlp; + register const struct tos_metric *tosp; + register const struct in_addr *ap; + register const struct aslametric *almp; + register const struct mcla *mcp; + register const u_int32_t *lp; + register int j, k; + + if (ospf_print_lshdr(&lsap->ls_hdr)) + return (1); + TCHECK(lsap->ls_hdr.ls_length); + ls_end = (u_char *)lsap + ntohs(lsap->ls_hdr.ls_length); + switch (lsap->ls_hdr.ls_type) { + + case LS_TYPE_ROUTER: + TCHECK(lsap->lsa_un.un_rla.rla_flags); + ospf_print_bits(ospf_rla_flag_bits, + lsap->lsa_un.un_rla.rla_flags); + + TCHECK(lsap->lsa_un.un_rla.rla_count); + j = ntohs(lsap->lsa_un.un_rla.rla_count); + TCHECK(lsap->lsa_un.un_rla.rla_link); + rlp = lsap->lsa_un.un_rla.rla_link; + while (j--) { + register struct rlalink *rln = + (struct rlalink *)((u_char *)(rlp + 1) + + ((rlp->link_toscount) * sizeof(*tosp))); + + TCHECK(*rln); + printf(" {"); /* } (ctags) */ + switch (rlp->link_type) { + + case RLA_TYPE_VIRTUAL: + printf(" virt"); + /* Fall through */ + + case RLA_TYPE_ROUTER: + printf(" nbrid %s if %s", + ipaddr_string(&rlp->link_id), + ipaddr_string(&rlp->link_data)); + break; + + case RLA_TYPE_TRANSIT: + printf(" dr %s if %s", + ipaddr_string(&rlp->link_id), + ipaddr_string(&rlp->link_data)); + break; + + case RLA_TYPE_STUB: + printf(" net %s mask %s", + ipaddr_string(&rlp->link_id), + ipaddr_string(&rlp->link_data)); + break; + + default: + /* { (ctags) */ + printf(" ??RouterLinksType %d?? }", + rlp->link_type); + return (0); + } + printf(" tos 0 metric %d", ntohs(rlp->link_tos0metric)); + tosp = (struct tos_metric *) + ((sizeof rlp->link_tos0metric) + (u_char *) rlp); + for (k = 0; k < (int) rlp->link_toscount; ++k, ++tosp) { + TCHECK(*tosp); + printf(" tos %d metric %d", + tosp->tos_type, + ntohs(tosp->tos_metric)); + } + /* { (ctags) */ + printf(" }"); + rlp = rln; + } + break; + + case LS_TYPE_NETWORK: + TCHECK(lsap->lsa_un.un_nla.nla_mask); + printf(" mask %s rtrs", + ipaddr_string(&lsap->lsa_un.un_nla.nla_mask)); + ap = lsap->lsa_un.un_nla.nla_router; + while ((u_char *)ap < ls_end) { + TCHECK(*ap); + printf(" %s", ipaddr_string(ap)); + ++ap; + } + break; + + case LS_TYPE_SUM_IP: + TCHECK(lsap->lsa_un.un_nla.nla_mask); + printf(" mask %s", + ipaddr_string(&lsap->lsa_un.un_sla.sla_mask)); + /* Fall through */ + + case LS_TYPE_SUM_ABR: + TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); + lp = lsap->lsa_un.un_sla.sla_tosmetric; + while ((u_char *)lp < ls_end) { + register u_int32_t ul; + + TCHECK(*lp); + ul = ntohl(*lp); + printf(" tos %d metric %d", + (ul & SLA_MASK_TOS) >> SLA_SHIFT_TOS, + ul & SLA_MASK_METRIC); + ++lp; + } + break; + + case LS_TYPE_ASE: + TCHECK(lsap->lsa_un.un_nla.nla_mask); + printf(" mask %s", + ipaddr_string(&lsap->lsa_un.un_asla.asla_mask)); + + TCHECK(lsap->lsa_un.un_sla.sla_tosmetric); + almp = lsap->lsa_un.un_asla.asla_metric; + while ((u_char *)almp < ls_end) { + register u_int32_t ul; + + TCHECK(almp->asla_tosmetric); + ul = ntohl(almp->asla_tosmetric); + printf(" type %d tos %d metric %d", + (ul & ASLA_FLAG_EXTERNAL) ? 2 : 1, + (ul & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS, + (ul & ASLA_MASK_METRIC)); + TCHECK(almp->asla_forward); + if (almp->asla_forward.s_addr) { + printf(" forward %s", + ipaddr_string(&almp->asla_forward)); + } + TCHECK(almp->asla_tag); + if (almp->asla_tag.s_addr) { + printf(" tag %s", + ipaddr_string(&almp->asla_tag)); + } + ++almp; + } + break; + + case LS_TYPE_GROUP: + /* Multicast extensions as of 23 July 1991 */ + mcp = lsap->lsa_un.un_mcla; + while ((u_char *)mcp < ls_end) { + TCHECK(mcp->mcla_vid); + switch (ntohl(mcp->mcla_vtype)) { + + case MCLA_VERTEX_ROUTER: + printf(" rtr rtrid %s", + ipaddr_string(&mcp->mcla_vid)); + break; + + case MCLA_VERTEX_NETWORK: + printf(" net dr %s", + ipaddr_string(&mcp->mcla_vid)); + break; + + default: + printf(" ??VertexType %u??", + (u_int32_t)ntohl(mcp->mcla_vtype)); + break; + } + ++mcp; + } + } + + /* { (ctags) */ + fputs(" }", stdout); + return (0); +trunc: + fputs(" }", stdout); + return (1); +} + +static int +ospf_decode_v2(register const struct ospfhdr *op, + register const u_char *dataend) +{ + register const struct in_addr *ap; + register const struct lsr *lsrp; + register const struct lsa_hdr *lshp; + register const struct lsa *lsap; + register char sep; + register int i; + + switch (op->ospf_type) { + + case OSPF_TYPE_UMD: + /* + * Rob Coltun's special monitoring packets; + * do nothing + */ + break; + + case OSPF_TYPE_HELLO: + if (vflag) { + TCHECK(op->ospf_hello.hello_deadint); + ospf_print_bits(ospf_option_bits, + op->ospf_hello.hello_options); + printf(" mask %s int %d pri %d dead %u", + ipaddr_string(&op->ospf_hello.hello_mask), + ntohs(op->ospf_hello.hello_helloint), + op->ospf_hello.hello_priority, + (u_int32_t)ntohl(op->ospf_hello.hello_deadint)); + } + TCHECK(op->ospf_hello.hello_dr); + if (op->ospf_hello.hello_dr.s_addr != 0) + printf(" dr %s", + ipaddr_string(&op->ospf_hello.hello_dr)); + TCHECK(op->ospf_hello.hello_bdr); + if (op->ospf_hello.hello_bdr.s_addr != 0) + printf(" bdr %s", + ipaddr_string(&op->ospf_hello.hello_bdr)); + if (vflag) { + printf(" nbrs"); + ap = op->ospf_hello.hello_neighbor; + while ((u_char *)ap < dataend) { + TCHECK(*ap); + printf(" %s", ipaddr_string(ap)); + ++ap; + } + } + break; /* HELLO */ + + case OSPF_TYPE_DB: + TCHECK(op->ospf_db.db_options); + ospf_print_bits(ospf_option_bits, op->ospf_db.db_options); + sep = ' '; + TCHECK(op->ospf_db.db_flags); + if (op->ospf_db.db_flags & OSPF_DB_INIT) { + printf("%cI", sep); + sep = '/'; + } + if (op->ospf_db.db_flags & OSPF_DB_MORE) { + printf("%cM", sep); + sep = '/'; + } + if (op->ospf_db.db_flags & OSPF_DB_MASTER) { + printf("%cMS", sep); + sep = '/'; + } + TCHECK(op->ospf_db.db_seq); + printf(" S %X", (u_int32_t)ntohl(op->ospf_db.db_seq)); + + if (vflag) { + /* Print all the LS adv's */ + lshp = op->ospf_db.db_lshdr; + + while (!ospf_print_lshdr(lshp)) { + /* { (ctags) */ + printf(" }"); + ++lshp; + } + } + break; + + case OSPF_TYPE_LSR: + if (vflag) { + lsrp = op->ospf_lsr; + while ((u_char *)lsrp < dataend) { + TCHECK(*lsrp); + printf(" {"); /* } (ctags) */ + ospf_print_ls_type(ntohl(lsrp->ls_type), + &lsrp->ls_stateid, + &lsrp->ls_router, + "LinkStateType %d"); + /* { (ctags) */ + printf(" }"); + ++lsrp; + } + } + break; + + case OSPF_TYPE_LSU: + if (vflag) { + lsap = op->ospf_lsu.lsu_lsa; + TCHECK(op->ospf_lsu.lsu_count); + i = ntohl(op->ospf_lsu.lsu_count); + while (i--) { + if (ospf_print_lsa(lsap)) + goto trunc; + lsap = (struct lsa *)((u_char *)lsap + + ntohs(lsap->ls_hdr.ls_length)); + } + } + break; + + + case OSPF_TYPE_LSA: + if (vflag) { + lshp = op->ospf_lsa.lsa_lshdr; + + while (!ospf_print_lshdr(lshp)) { + /* { (ctags) */ + printf(" }"); + ++lshp; + } + } + break; + + default: + printf("v2 type %d", op->ospf_type); + break; + } + return (0); +trunc: + return (1); +} + +void +ospf_print(register const u_char *bp, register u_int length, + register const u_char *bp2) +{ + register const struct ospfhdr *op; + register const struct ip *ip; + register const u_char *dataend; + register const char *cp; + + op = (struct ospfhdr *)bp; + ip = (struct ip *)bp2; + /* Print the source and destination address */ + (void) printf("%s > %s:", + ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst)); + + /* If the type is valid translate it, or just print the type */ + /* value. If it's not valid, say so and return */ + TCHECK(op->ospf_type); + cp = tok2str(type2str, "type%d", op->ospf_type); + printf(" OSPFv%d-%s %d:", op->ospf_version, cp, length); + if (*cp == 't') + return; + + TCHECK(op->ospf_len); + if (length != ntohs(op->ospf_len)) { + printf(" [len %d]", ntohs(op->ospf_len)); + return; + } + dataend = bp + length; + + /* Print the routerid if it is not the same as the source */ + TCHECK(op->ospf_routerid); + if (ip->ip_src.s_addr != op->ospf_routerid.s_addr) + printf(" rtrid %s", ipaddr_string(&op->ospf_routerid)); + + TCHECK(op->ospf_areaid); + if (op->ospf_areaid.s_addr != 0) + printf(" area %s", ipaddr_string(&op->ospf_areaid)); + else + printf(" backbone"); + + if (vflag) { + /* Print authentication data (should we really do this?) */ + TCHECK2(op->ospf_authdata[0], sizeof(op->ospf_authdata)); + switch (ntohs(op->ospf_authtype)) { + + case OSPF_AUTH_NONE: + break; + + case OSPF_AUTH_SIMPLE: + printf(" auth \""); + (void)fn_printn(op->ospf_authdata, + sizeof(op->ospf_authdata), NULL); + printf("\""); + break; + + default: + printf(" ??authtype-%d??", ntohs(op->ospf_authtype)); + return; + } + } + /* Do rest according to version. */ + switch (op->ospf_version) { + + case 2: + /* ospf version 2 */ + if (ospf_decode_v2(op, dataend)) + goto trunc; + break; + + default: + printf(" ospf [version %d]", op->ospf_version); + break; + } /* end switch on version */ + + return; +trunc: + fputs(tstr, stdout); +} diff --git a/tcpdump.tproj/print-pim.c b/tcpdump.tproj/print-pim.c new file mode 100644 index 0000000..3fb9909 --- /dev/null +++ b/tcpdump.tproj/print-pim.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-pim.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +void +pim_print(register const u_char *bp, register u_int len) +{ + register const u_char *ep; + register u_char type; + + ep = (const u_char *)snapend; + if (bp >= ep) + return; + + type = bp[1]; + + switch (type) { + case 0: + (void)printf(" Query"); + break; + + case 1: + (void)printf(" Register"); + break; + + case 2: + (void)printf(" Register-Stop"); + break; + + case 3: + (void)printf(" Join/Prune"); + break; + + case 4: + (void)printf(" RP-reachable"); + break; + + case 5: + (void)printf(" Assert"); + break; + + case 6: + (void)printf(" Graft"); + break; + + case 7: + (void)printf(" Graft-ACK"); + break; + + case 8: + (void)printf(" Mode"); + break; + + default: + (void)printf(" [type %d]", type); + break; + } +} diff --git a/tcpdump.tproj/print-ppp.c b/tcpdump.tproj/print-ppp.c new file mode 100644 index 0000000..9fd2a49 --- /dev/null +++ b/tcpdump.tproj/print-ppp.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-ppp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#ifdef PPP +#include +#include +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +/* XXX This goes somewhere else. */ +#define PPP_HDRLEN 4 + +void +ppp_if_print(u_char *user, const struct pcap_pkthdr *h, + register const u_char *p) +{ + register u_int length = h->len; + register u_int caplen = h->caplen; + const struct ip *ip; + + ts_print(&h->ts); + + if (caplen < PPP_HDRLEN) { + printf("[|ppp]"); + goto out; + } + + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = p; + snapend = p + caplen; + + if (eflag) + printf("%c %4d %02x %04x: ", p[0] ? 'O' : 'I', length, + p[1], ntohs(*(u_short *)&p[2])); + + length -= PPP_HDRLEN; + ip = (struct ip *)(p + PPP_HDRLEN); + ip_print((const u_char *)ip, length); + + if (xflag) + default_print((const u_char *)ip, caplen - PPP_HDRLEN); +out: + putchar('\n'); +} +#else +#include +#include + +#include + +#include "interface.h" +void +ppp_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + error("not configured for ppp"); + /* NOTREACHED */ +} +#endif diff --git a/tcpdump.tproj/print-rip.c b/tcpdump.tproj/print-rip.c new file mode 100644 index 0000000..7c87af7 --- /dev/null +++ b/tcpdump.tproj/print-rip.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-rip.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +struct rip { + u_char rip_cmd; /* request/response */ + u_char rip_vers; /* protocol version # */ + u_short rip_zero2; /* unused */ +}; +#define RIPCMD_REQUEST 1 /* want info */ +#define RIPCMD_RESPONSE 2 /* responding to request */ +#define RIPCMD_TRACEON 3 /* turn tracing on */ +#define RIPCMD_TRACEOFF 4 /* turn it off */ +#define RIPCMD_POLL 5 /* want info from everybody */ +#define RIPCMD_POLLENTRY 6 /* poll for entry */ + +struct rip_netinfo { + u_short rip_family; + u_short rip_tag; + u_int32_t rip_dest; + u_int32_t rip_dest_mask; + u_int32_t rip_router; + u_int32_t rip_metric; /* cost of route */ +}; + +static void +rip_entry_print(register int vers, register const struct rip_netinfo *ni) +{ + register u_char *cp, *ep; + + if (EXTRACT_16BITS(&ni->rip_family) != AF_INET) { + + printf(" [family %d:", EXTRACT_16BITS(&ni->rip_family)); + cp = (u_char *)&ni->rip_tag; + ep = (u_char *)&ni->rip_metric + sizeof(ni->rip_metric); + for (; cp < ep; cp += 2) + printf(" %04x", EXTRACT_16BITS(cp)); + printf("]"); + } else if (vers < 2) { + /* RFC 1058 */ + printf(" %s", ipaddr_string(&ni->rip_dest)); + } else { + /* RFC 1723 */ + printf(" {%s", ipaddr_string(&ni->rip_dest)); + if (ni->rip_dest_mask) + printf("/%s", ipaddr_string(&ni->rip_dest_mask)); + if (ni->rip_router) + printf("->%s", ipaddr_string(&ni->rip_router)); + if (ni->rip_tag) + printf(" tag %04x", EXTRACT_16BITS(&ni->rip_tag)); + printf("}"); + } + printf("(%d)", EXTRACT_32BITS(&ni->rip_metric)); +} + +void +rip_print(const u_char *dat, u_int length) +{ + register const struct rip *rp; + register const struct rip_netinfo *ni; + register int i, j, trunc; + + i = min(length, snapend - dat) - sizeof(*rp); + if (i < 0) + return; + + rp = (struct rip *)dat; + switch (rp->rip_cmd) { + + case RIPCMD_REQUEST: + printf(" rip-req %d", length); + break; + + case RIPCMD_RESPONSE: + j = length / sizeof(*ni); + if (j * sizeof(*ni) != length - 4) + printf(" rip-resp %d[%d]:", j, length); + else + printf(" rip-resp %d:", j); + trunc = ((i / sizeof(*ni)) * sizeof(*ni) != i); + ni = (struct rip_netinfo *)(rp + 1); + for (; (i -= sizeof(*ni)) >= 0; ++ni) + rip_entry_print(rp->rip_vers, ni); + if (trunc) + printf("[|rip]"); + break; + + case RIPCMD_TRACEON: + printf(" rip-traceon %d: \"", length); + (void)fn_print((const u_char *)(rp + 1), snapend); + fputs("\"\n", stdout); + break; + + case RIPCMD_TRACEOFF: + printf(" rip-traceoff %d", length); + break; + + case RIPCMD_POLL: + printf(" rip-poll %d", length); + break; + + case RIPCMD_POLLENTRY: + printf(" rip-pollentry %d", length); + break; + + default: + printf(" rip-#%d %d", rp->rip_cmd, length); + break; + } + switch (rp->rip_vers) { + + case 1: + case 2: + break; + + default: + printf(" [vers %d]", rp->rip_vers); + break; + } +} diff --git a/tcpdump.tproj/print-skip.c b/tcpdump.tproj/print-skip.c new file mode 100644 index 0000000..d9f5059 --- /dev/null +++ b/tcpdump.tproj/print-skip.c @@ -0,0 +1,943 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: print-skip.c,v 1.2 1996/07/13 11:01:29 mickey Exp $ */ + +/* + * Copyright (c) 1995 Sun Microsystems, Inc. + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + + * IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF + * SUN MICROSYSTEMS, INC. HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + + * SUN MICROSYSTEMS, INC. SPECIFICALLY DISCLAIMS ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + * THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND SUN + * MICROSYSTEMS, INC. HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, + * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +#define MAX_ALGS (256) + +int skipflag = 0; + +const int skip_max_algs = MAX_ALGS; + +char *old_skip_crypt_algs[MAX_ALGS] = { + "none", /* 0 */ + "des_cbc", /* 1 */ + "rc2_cbc", /* 2 */ + "rc4(40bit)", /* 3 */ + "rc4(128bit)", /* 4 */ + "des_ede-2", /* 5 */ + "des_ede-3", /* 6 */ + "idea", /* 7 */ + "", /* 8 */ + "", /* 9 */ + "simplecrypt" /* 10 */ + }; + + +char * +skip_alg_to_name(char *table[], int alg) +{ + if (alg > skip_max_algs) { + return (""); + } + if (alg < 0) { + return (""); + } + if (table[alg] == NULL) { + return (""); + } + if (strlen(table[alg]) == 0) { + return (""); + } + return (table[alg]); +} + +/* + * This is what an OLD skip encrypted-authenticated packet looks like: + * + * + * 0 1 2 3 + * --------------------------------- + * | | + * / Clear IP Header / + * | | IP protocol = IPSP + * --------------------------------- + * | | + * | IPSP header | + * | | + * --------------------------------- + * | | + * / Protected IPSP Payload / + * / / + * | | + * --------------------------------- + * + * + * The format of the IPSP header for encrypted-encapsulated mode is shown below. * The fields are transmitted from left to right. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver. |E|A|C|S|B|R| zero | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Kij alg. | Kp alg. | reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Optional boxid field | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Kp encrypted in Kij... (typically 8-16 bytes) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Message Indicator (e.g IV)... (typically 8-16 bytes) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Protected IPSP Payload... + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + * Field values: + * Ver.: protocol version + * E: 1 if packet is encrypted, 0 otherwise + * A: 1 if packet is authenticated, 0 otherwise + * C: 1 if packet is compressed before encryption, 0 otherwise + * S: 1 if packet is sequenced, 0 otherwise + * B: 1 if packet is tunneled (header contains boxid), 0 otherwise + * R: reserved (should be 0 until specified) + * + */ +/* + * per-algorithm encrytped key sizes... + */ +unsigned char old_skip_ekp_sizes[MAX_ALGS] = { + 8, /* plaintext */ + 8, /* DES */ + 8, /* RC2 */ + 8, /* RC4 (40 bit) */ + 16, /* RC4 (128 bit) */ + 16, /* 3DES 2 */ + 24, /* 3DES 3 */ + 16, /* IDEA */ + 0, /* */ + 0, /* */ + 8, /* simplecrypt */ + }; +/* + * per-algorithm message indicator sizes... + */ +unsigned char old_skip_mid_sizes[MAX_ALGS] = { + 8, /* plaintext */ + 8, /* DES */ + 8, /* RC2 */ + 8, /* RC4 40 bit */ + 8, /* RC4 128 bit */ + 8, /* 3DES 2 */ + 8, /* 3DES 3 */ + 8, /* IDEA */ + 0, /* */ + 0, /* */ + 8, /* simplecrypt */ + }; + +void skip_print_old(register const u_char *bp, register int length, + const u_char *bp2) +{ + struct ip *ip; + const u_char *end; + u_char *p; + unsigned char kij_alg, kp_alg, *c; + unsigned short i; + unsigned short len; + int boxid; + int node; + + ip=(struct ip *)bp2; + p=(u_char *)bp; + end=bp+length; + printf("SKIP: *** OLD SKIP ***\n"); + printf("OSKIP: %s>%s:%d",ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst),length); + if (!skipflag) + return; + printf("\nOSKIP: SAID byte 1= 0x%02x\n",*p); + printf("OSKIP: xxxx .... = version %d\n", (int) (*p & 0xf0) >> 4); + if (*p & 0x08) { + printf("OSKIP: .... 1... = encrypted\n"); + } else { + printf("OSKIP: .... 0... = not encrypted\n"); + } + + if (*p & 0x04) { + printf("OSKIP: .... .1.. = authenticated\n"); + } else { + printf("OSKIP: .... .0.. = not authenticated\n"); + } + + if (*p & 0x02) { + printf("OSKIP: .... ..1. = compressed\n"); + } else { + printf("OSKIP: .... ..0. = not compressed\n"); + } + + if (*p & 0x01) { + printf("OSKIP: .... ...1 = sequenced\n"); + } else { + printf("OSKIP: .... ...0 = not sequenced\n"); + } + + p++; + + printf("OSKIP: SAID byte 2 = 0x%02x\n", *p); + + if (*p & 0x80) { + node=1; + printf("OSKIP: 1... .... = Node ID present\n"); + } else { + node=0; + printf("OSKIP: 0... .... = no Node ID present\n"); + } + + if (*p & 0x40) { + printf("OSKIP: .1.. .... = \n"); + } else { + printf("OSKIP: .0.. .... = \n"); + } + + if (*p & 0x20) { + printf("OSKIP: ..1. .... = \n"); + } else { + printf("OSKIP: ..0. .... = \n"); + } + + if (*p & 0x10) { + printf("OSKIP: ...1 .... = \n"); + } else { + printf("OSKIP: ...0 .... = \n"); + } + p++; + printf("OSKIP: SAID byte 3 = 0x%02x\n", *p); + + p++; + printf("OSKIP: SAID byte 4 = 0x%02x\n", *p); + + p++; + + kij_alg = *p; + printf("OSKIP: Kij alg (key encryption algorithm) = 0x%02x (%s)\n", + kij_alg, skip_alg_to_name(old_skip_crypt_algs,kij_alg)); + + p++; + + kp_alg = *p; + printf("OSKIP: Kp alg (traffic encryption algorithm) = 0x%02x (%s)\n", + kp_alg, skip_alg_to_name(old_skip_crypt_algs,kp_alg)); + + p++; + + /* + * the skip reserved field + */ + printf("OSKIP: reserved byte 1 = 0x%02x\n", *p++); + printf("OSKIP: reserved byte 2 = 0x%02x\n", *p++); + + if (node) { + /* + * boxid field + */ + if ((end - p) < sizeof(boxid)) { + return; + } + c = (unsigned char *) &boxid; + *c++ = *p++; + *c++ = *p++; + *c++ = *p++; + *c++ = *p++; + + printf("OSKIP: Node ID = 0x%08x\n", ntohl(boxid)); + } + + /* + * encrypted kp (ekp) field + */ + + /* + * do this with a for-loop to avoid alignment problems and the + * overhead of calling bcopy() + */ + len = old_skip_ekp_sizes[kp_alg]; + if ((unsigned short) (end - p) < len) { + return; + } + + printf("OSKIP: encrypted Kp: "); + for (i = 0; i < len; i++) { + printf("%02x ", (unsigned char) *p++); + } + printf("\n"); + + /* + * message indicator (mid) field + */ + len = old_skip_mid_sizes[kp_alg]; + if ((unsigned short) (end - p) < len) { + return; + } + printf("OSKIP: message indicator field: "); + for (i = 0; i < len; i++) { + printf("%02x ", (unsigned char) *p++); + } + printf("\n"); +} + + + +/* + * The following part is (c) by G. Caronni -- 29.11.95 + * + * This code is in the public domain; do with it what you wish. + * + * NO WARRANTY, NO SUPPORT, NO NOTHING! + */ + + +/* + * This is what a NEW skip encrypted-authenticated packet looks like: + * + * + * 0 1 2 3 + * --------------------------------- + * | | + * / Clear IP Header / + * | | IP protocol = SKIP + * --------------------------------- + * | | + * | SKIP header | + * | | + * --------------------------------- + * | | + * | Auth Header & payload | + * | | + * --------------------------------- + * | | + * | ESP header and SPI | + * | | + * --------------------------------- + * | | + * / Protected ESP Payload / + * | | + * --------------------------------- + * + * + * The format of the SKIP header for encrypted-encapsulated mode is shown below. * The fields are transmitted from left to right. + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | Rsvd | Source NSID | Dest NSID | NEXT HEADER | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Counter n | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Kij Alg | Crypt Alg | MAC Alg | Comp Alg | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Kp encrypted in Kijn... (typically 8-16 bytes) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source Master Key-ID (If Source NSID is non-zero) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Destination Master Key-ID (If Dest NSID is non-zero) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + + + + + +/* + * per name space key ID sizes... + */ +unsigned char skip_nsid_sizes[MAX_ALGS] = { + 0, /* 0 none */ + 4, /* 1 IP v4 Address Space */ + 4, /* 2 POSIX/XOPEN User Ids */ + 16, /* 3 IPv6 Address Space */ + 16, /* 4 MD5 of DNS Names */ + 16, /* 5 MD5 of ISO ASN.1 DN encoding */ + 16, /* 6 MD5 of US Social Security number */ + 6, /* 7 802.x MAC Address */ + 16, /* 8 MD5 of public Value */ + 16, /* 9 MD5 of RFC822 Mailbox Address */ + 16, /* 10 MD5 of Bank Account # */ + 16, /* 11 MD5 of NIS Name */ + }; + + +/* + * per Kp algorithm encrypted Kp sizes... (Kij alg does not matter for now) + */ +unsigned char skip_ekp_sizes[MAX_ALGS] = { + 0, /* 0 plaintext */ + 8, /* 1 DES_CBC */ + 24, /* 2 3 key triple DES-EDE-CBC */ + 0, /* 3 */ + 0, /* 4 */ + 0, /* 5 */ + 0, /* 6 */ + 0, /* 7 */ + 0, /* 8 */ + 0, /* 9 */ /* 10 .. 249 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 8, /* 250 RC4-40 */ + 16, /* 251 RC4-128 */ + 8, /* 252 simple crypt */ + 16, /* 253 IDEA */ + 0, /* 254 */ + 0 /* 255 */ + }; + + +/* + * per-algorithm NSID names ... + */ +char *skip_nsid_names[MAX_ALGS] = { + "none", /* 0 */ + "IPv4", /* 1 */ + "Posix/Xopen UID", /* 2 */ + "IPv6", /* 3 */ + "MD5 DNS", /* 4 */ + "MD5 ASN.1 DN", /* 5 */ + "MD5 U.S. Soc. #", /* 6 */ + "802.x MAC", /* 7 */ + "MD5 DH Public Key",/* 8 */ + "MD5 RFC822 Mail", /* 9 */ + "MD5 Bank Account", /* 10 */ + "MD5 NIS Name", /* 11 */ + }; + + +/* + * per-algorithm Kij alg names ... + */ +char *skip_kij_names[MAX_ALGS] = { + "none", /* 0 */ + "DES-CBC", /* 1 */ + "3DES3-EDE-CBC", /* 2 */ + "IDEA-CBC", /* 3 */ + }; + + +/* for padding of ekp */ + +char skip_kij_sizes[MAX_ALGS] = { + 0, /* 0 none */ + 8, /* 1 des-cbc */ + 8, /* 2 3des3-ede-cbc */ + 8, /* 3 idea-cbc */ + }; + + +/* + * per-algorithm Crypt alg names ... + */ +char *skip_crypt_names[MAX_ALGS] = { + "none", /* 0 */ + "DES-CBC", /* 1 */ + "3 key DES-EDE-CBC", /* 2 */ + "", /* 3 */ + "", /* 4 */ + "", /* 5 */ + "", /* 6 */ + "", /* 7 */ + "", /* 8 */ + "", /* 9 */ /* 10 .. 249 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + "RC4-40", /* 250 */ + "RC4-128", /* 251 */ + "simple crypt", /* 252 */ + "IDEA CBC", /* 253 */ + "", /* 254 */ + "" /* 255 */ + }; + + +/* + * per-algorithm Auth alg names ... + */ +char *skip_auth_names[MAX_ALGS] = { + "none", /* 0 */ + "keyed MD5", /* 1 */ + "DES-CBC MAC", /* 2 */ + "Keyed SHA", /* 3 */ + }; + + +char skip_auth_sizes[MAX_ALGS] = { + 0, /* 0 none */ + 16, /* 1 keyed MD5 */ + 8, /* 2 DES-CBC MAC */ + 20, /* 3 Keyed SHA */ + }; + + +/* + * per-algorithm Crypt alg IV sizes ... + */ +char skip_crypt_sizes[MAX_ALGS] = { + 0, /* 0 none */ + 8, /* 1 DES-CBC */ + 8, /* 2 3key DES-EDE-CBC */ + 0, /* 3 */ + 0, /* 4 */ + 0, /* 5 */ + 0, /* 6 */ + 0, /* 7 */ + 0, /* 8 */ + 0, /* 9 */ /* 10 .. 249 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 8, /* 250 RC4-40 */ + 8, /* 251 RC4-128 */ + 8, /* 252 simple crypt */ + 8, /* 253 IDEA CBC */ + 0, /* 254 */ + 0 /* 255 */ + }; + + +#ifndef IPPROTO_ESP +#define IPPROTO_ESP 50 +#endif +#ifndef IPPROTO_AH +#define IPPROTO_AH 51 +#endif +#ifndef IPPROTO_SKIP +#define IPPROTO_SKIP 57 +#endif +#ifndef IPPROTO_OSKIP +#define IPPROTO_OSKIP 79 +#endif + +static int expected_auth_size=0; +static int expected_iv_size=0; + +char *skip_protocol_name(int p) +{ + switch(p) { + case IPPROTO_IP: return "IP"; + case IPPROTO_ICMP: return "ICMP"; + case IPPROTO_IGMP: return "IGMP"; + case IPPROTO_ENCAP: return "ENCAP"; + case IPPROTO_TCP: return "TCP"; + case IPPROTO_EGP: return "EGP"; + case IPPROTO_UDP: return "UDP"; + case IPPROTO_ESP: return "ESP"; + case IPPROTO_AH: return "AH"; + case IPPROTO_SKIP: return "SKIP"; + case IPPROTO_ND: return "ND"; + case IPPROTO_OSKIP: return "OLD-SKIP"; + case IPPROTO_RAW: return "RAW IP"; + default: return ""; + } +} + +void skip_print_next(u_char nxt, const u_char *p, int len, const u_char *bp2) +{ + switch(nxt) { + case IPPROTO_IP: ip_print(p,len); break; + case IPPROTO_ICMP: icmp_print(p,bp2); break; + case IPPROTO_TCP: tcp_print(p,len,bp2); break; + case IPPROTO_UDP: udp_print(p,len,bp2); break; + case IPPROTO_ESP: esp_print(p,len,bp2); break; + case IPPROTO_AH: ah_print(p,len,bp2); break; + case IPPROTO_SKIP: skip_print(p,len,bp2); break; + default: break; + } +} + +void skip_print(register const u_char *bp, register int length, + const u_char *bp2) +{ + struct ip *ip; + const u_char *end; + const u_char *p; + unsigned char kij_alg, crypt_alg, auth_alg, snsid, dnsid, nxt; + unsigned short i; + unsigned short len; + u_int n; + time_t full_n; + + ip=(struct ip *)bp2; + p=bp; + end=bp+length%s:%d SKIP",ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst),length); + if (!skipflag) + return; + + + if ((unsigned short) (end - p) < 4) { + printf("[SKIP|] (truncated)\n"); + return; + } + + printf("\nSKIP: version\t\t\t%d\n", (int) (*p & 0xf0) >> 4); + if (*p & 0xf) + printf("SKIP: version byte \t\treserved,\tis now 0x%x\n", + (int) (*p & 0xf)); + p++; + + snsid = *p; + printf("SKIP: Source NSID\t\t0x%02x\t\t%s\n", + snsid, skip_alg_to_name(skip_nsid_names,snsid)); + p++; + + dnsid = *p; + printf("SKIP: Destination NSID\t\t0x%02x\t\t%s\n", + dnsid, skip_alg_to_name(skip_nsid_names,dnsid)); + p++; + + nxt = *p; + printf("SKIP: Next Protocol Field\t0x%02x\t\t%s\n", nxt, + skip_protocol_name(nxt)); + + p++; + + if ((unsigned short) (end - p) < 4) { + printf("[SKIP|] (truncated)\n"); + return; + } + + n=*p++<<24; + n+=*p++<<16; + n+=*p++<<8; + n+=*p; + full_n=(((365*25+6)*24)+n)*3600; + printf("SKIP: Counter n Field\t\t0x%08x\t%s", n, + asctime(gmtime(&full_n))); + p++; + + if ((unsigned short) (end - p) < 4) { + printf("[SKIP|] (truncated)\n"); + return; + } + + kij_alg = *p; + printf("SKIP: Kij alg (key encryption)\t0x%02x\t\t%s\n", + kij_alg, skip_alg_to_name(skip_kij_names,kij_alg)); + p++; + + crypt_alg = *p; + expected_iv_size=skip_crypt_sizes[crypt_alg]; + printf("SKIP: Crypt Alg\t\t\t0x%02x\t\t%s\n", + crypt_alg, skip_alg_to_name(skip_crypt_names,crypt_alg)); + p++; + + auth_alg = *p; + expected_auth_size=skip_auth_sizes[auth_alg]; + printf("SKIP: Auth Alg\t\t\t0x%02x\t\t%s\n", + auth_alg, skip_alg_to_name(skip_auth_names,auth_alg)); + p++; + + if (*p) printf("SKIP: compression\t\treserved,\tis now0x%02x\n", + (int) *p++); + else p++; + + /* + * encrypted kp (ekp) field + */ + + if (kij_alg==0 && (crypt_alg || auth_alg)) { + printf("Warning: Kij Alg. undefined, but Auth. or Crypt. used!"); + printf("Warning: Assuming empty Kp\n"); + crypt_alg=auth_alg=0; + } + /* + * do this with a for-loop to avoid alignment problems and the + * overhead of calling bcopy() + */ + len = skip_ekp_sizes[crypt_alg]; + len = len>(int)skip_auth_sizes[auth_alg]?len:skip_auth_sizes[auth_alg]; + if (len && skip_kij_sizes[kij_alg] && len % skip_kij_sizes[kij_alg]) { + len += skip_kij_sizes[kij_alg] - (len%skip_kij_sizes[kij_alg]); + } + if ((unsigned short) (end - p) < len) { + printf("[SKIP|] (truncated)\n"); + return; + } + + printf("SKIP: Encrypted Kp\t\t"); + for (i = 0; i < len; i++) { + printf("%02x ", (unsigned char) *p++); + } + printf("\n"); + + + if (snsid) { + /* + * Source Master Key-ID field + */ + if ((end - p) < skip_nsid_sizes[snsid]) { + printf("[SKIP|] (truncated)\n"); + return; + } + printf("SKIP: Source Master Key-ID\t"); + if (snsid==1) { + printf("%s",ipaddr_string(p)); + p+=skip_nsid_sizes[snsid]; + } else { + for (i = 0; i < skip_nsid_sizes[snsid]; i++) { + printf("%02x ", (unsigned char) *p++); + } + } + printf("\n"); + } + + if (dnsid) { + /* + * Destination Master Key-ID field + */ + if ((end - p) < skip_nsid_sizes[dnsid]) { + printf("[SKIP|] (truncated)\n"); + return; + } + printf("SKIP: Dest. Master Key-ID\t"); + if (dnsid==1) { + printf("%s",ipaddr_string(p)); + p+=skip_nsid_sizes[dnsid]; + } else { + for (i = 0; i < skip_nsid_sizes[dnsid]; i++) { + printf("%02x ", (unsigned char) *p++); + } + } + printf("\n"); + } + if (p%s:%d",ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst),length); + if (!skipflag) + return; + + if (end-p <4) { + printf("[SKIP-AH|]\n"); + return; + } + + nxt = *p; + printf("\nSKIP-AH: Next Protocol Field\t0x%02x\t\t%s\n", nxt, + skip_protocol_name(nxt)); + p++; + + len= 4 * (int) *p; + printf("SKIP-AH: length\t\t\t%d\n", len); + + p++; + + if (*p) printf("SKIP-AH: byte 3\t\t\treserved,\tis now0x%02x\n", + (int) *p++); + else p++; + if (*p) printf("SKIP-AH: byte 4\t\t\treserved,\tis now0x%02x\n", + (int) *p++); + else p++; + + if (end-p <4) { + printf("[SKIP-AH|]\n"); + return; + } + + spi=*p++<<24; + spi+=*p++<<16; + spi+=*p++<<8; + spi+=*p; + printf("SKIP-AH: SPI\t\t\t0x%08x\t", spi ); + if (spi==0) { + printf("NO association\n"); + } else if (spi==1) { + printf("SKIP association\n"); + if (expected_auth_size) { + if (expected_auth_size != len) { + printf("Warning: Length does not match SKIP Auth Alg!\n"); + } + expected_auth_size=0; + } + } else if (spi<256) { + printf("UNKNOWN association\n"); + } else { + printf("DYNAMIC association\n"); + } + + p++; + + + /* + * authentication data + */ + + if ((unsigned short) (end - p) < len) { + printf("[SKIP-AH|] (truncated)\n"); + return; + } + + printf("SKIP-AH: Authentication Data\t"); + for (i = 0; i < len; i++) { + printf("%02x ", (unsigned char) *p++); + if (i%s:%d",ipaddr_string(&ip->ip_src), + ipaddr_string(&ip->ip_dst),length); + if (!skipflag) + return; + + if (end-p <4) { + printf("[SKIP-ESP|]\n"); + } + + spi=*p++<<24; + spi+=*p++<<16; + spi+=*p++<<8; + spi+=*p; + printf("\nSKIP-ESP: SPI\t\t\t0x%08x\t", spi ); + if (spi==0) { + printf("NO association\n"); + len=0; + } else if (spi==1) { + printf("SKIP association\n"); + len=expected_iv_size; + if (!expected_iv_size) { + printf("Warning: IV size not defined by SKIP Crypt Alg!\n"); + } else expected_iv_size=0; + } else if (spi<256) { + printf("UNKNOWN association\n"); + len=0; + } else { + printf("DYNAMIC association\n"); + len=0; + } + + p++; + + /* + * IV data + */ + + if ((unsigned short) (end - p) < len) { + printf("[SKIP-ESP|] (truncated)\n"); + return; + } + + printf("SKIP-ESP: Initalization Vector\t"); + if (len) { + for (i = 0; i < len; i++) { + printf("%02x ", (unsigned char) *p++); + if (i +#include +#include +#include +#include +#include +#include + +#if __STDC__ +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" /* must come after interface.h */ + +static u_int lastlen[2][256]; +static u_int lastconn = 255; + +static void sliplink_print(const u_char *, const struct ip *, u_int); +static void compressed_sl_print(const u_char *, const struct ip *, u_int, int); + +/* XXX BSD/OS 2.1 compatibility */ +#if !defined(SLIP_HDRLEN) && defined(SLC_BPFHDR) +#define SLIP_HDRLEN SLC_BPFHDR +#define SLX_DIR 0 +#define SLX_CHDR (SLC_BPFHDRLEN - 1) +#define CHDR_LEN (SLC_BPFHDR - SLC_BPFHDRLEN) +#endif + +void +sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + register u_int caplen = h->caplen; + register u_int length = h->len; + register const struct ip *ip; + + ts_print(&h->ts); + + if (caplen < SLIP_HDRLEN) { + printf("[|slip]"); + goto out; + } + /* + * Some printers want to get back at the link level addresses, + * and/or check that they're not walking off the end of the packet. + * Rather than pass them all the way down, we set these globals. + */ + packetp = p; + snapend = p + caplen; + + length -= SLIP_HDRLEN; + + ip = (struct ip *)(p + SLIP_HDRLEN); + + if (eflag) + sliplink_print(p, ip, length); + + ip_print((u_char *)ip, length); + + if (xflag) + default_print((u_char *)ip, caplen - SLIP_HDRLEN); + out: + putchar('\n'); +} + +static void +sliplink_print(register const u_char *p, register const struct ip *ip, + register u_int length) +{ + int dir; + u_int hlen; + + dir = p[SLX_DIR]; + putchar(dir == SLIPDIR_IN ? 'I' : 'O'); + putchar(' '); + + if (nflag) { + /* XXX just dump the header */ + register int i; + + for (i = SLX_CHDR; i < SLX_CHDR + CHDR_LEN - 1; ++i) + printf("%02x.", p[i]); + printf("%02x: ", p[SLX_CHDR + CHDR_LEN - 1]); + return; + } + switch (p[SLX_CHDR] & 0xf0) { + + case TYPE_IP: + printf("ip %d: ", length + SLIP_HDRLEN); + break; + + case TYPE_UNCOMPRESSED_TCP: + /* + * The connection id is stored in the IP protocol field. + * Get it from the link layer since sl_uncompress_tcp() + * has restored the IP header copy to IPPROTO_TCP. + */ + lastconn = ((struct ip *)&p[SLX_CHDR])->ip_p; + hlen = ip->ip_hl; + hlen += ((struct tcphdr *)&((int *)ip)[hlen])->th_off; + lastlen[dir][lastconn] = length - (hlen << 2); + printf("utcp %d: ", lastconn); + break; + + default: + if (p[SLX_CHDR] & TYPE_COMPRESSED_TCP) { + compressed_sl_print(&p[SLX_CHDR], ip, + length, dir); + printf(": "); + } else + printf("slip-%d!: ", p[SLX_CHDR]); + } +} + +static const u_char * +print_sl_change(const char *str, register const u_char *cp) +{ + register u_int i; + + if ((i = *cp++) == 0) { + i = EXTRACT_16BITS(cp); + cp += 2; + } + printf(" %s%d", str, i); + return (cp); +} + +static const u_char * +print_sl_winchange(register const u_char *cp) +{ + register short i; + + if ((i = *cp++) == 0) { + i = EXTRACT_16BITS(cp); + cp += 2; + } + if (i >= 0) + printf(" W+%d", i); + else + printf(" W%d", i); + return (cp); +} + +static void +compressed_sl_print(const u_char *chdr, const struct ip *ip, + u_int length, int dir) +{ + register const u_char *cp = chdr; + register u_int flags, hlen; + + flags = *cp++; + if (flags & NEW_C) { + lastconn = *cp++; + printf("ctcp %d", lastconn); + } else + printf("ctcp *"); + + /* skip tcp checksum */ + cp += 2; + + switch (flags & SPECIALS_MASK) { + case SPECIAL_I: + printf(" *SA+%d", lastlen[dir][lastconn]); + break; + + case SPECIAL_D: + printf(" *S+%d", lastlen[dir][lastconn]); + break; + + default: + if (flags & NEW_U) + cp = print_sl_change("U=", cp); + if (flags & NEW_W) + cp = print_sl_winchange(cp); + if (flags & NEW_A) + cp = print_sl_change("A+", cp); + if (flags & NEW_S) + cp = print_sl_change("S+", cp); + break; + } + if (flags & NEW_I) + cp = print_sl_change("I+", cp); + + /* + * 'hlen' is the length of the uncompressed TCP/IP header (in words). + * 'cp - chdr' is the length of the compressed header. + * 'length - hlen' is the amount of data in the packet. + */ + hlen = ip->ip_hl; + hlen += ((struct tcphdr *)&((int32_t *)ip)[hlen])->th_off; + lastlen[dir][lastconn] = length - (hlen << 2); + printf(" %d (%d)", lastlen[dir][lastconn], cp - chdr); +} +#else +#include +#include + +#include +#include + +#include "interface.h" +void +sl_if_print(u_char *user, const struct pcap_pkthdr *h, const u_char *p) +{ + + error("not configured for slip"); + /* NOTREACHED */ +} +#endif diff --git a/tcpdump.tproj/print-snmp.c b/tcpdump.tproj/print-snmp.c new file mode 100644 index 0000000..860be8a --- /dev/null +++ b/tcpdump.tproj/print-snmp.c @@ -0,0 +1,1063 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by John Robert LoVerso. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * This implementation has been influenced by the CMU SNMP release, + * by Steve Waldbusser. However, this shares no code with that system. + * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_. + * Earlier forms of this implementation were derived and/or inspired by an + * awk script originally written by C. Philip Wood of LANL (but later + * heavily modified by John Robert LoVerso). The copyright notice for + * that work is preserved below, even though it may not rightly apply + * to this file. + * + * This started out as a very simple program, but the incremental decoding + * (into the BE structure) complicated things. + * + # Los Alamos National Laboratory + # + # Copyright, 1990. The Regents of the University of California. + # This software was produced under a U.S. Government contract + # (W-7405-ENG-36) by Los Alamos National Laboratory, which is + # operated by the University of California for the U.S. Department + # of Energy. The U.S. Government is licensed to use, reproduce, + # and distribute this software. Permission is granted to the + # public to copy and use this software without charge, provided + # that this Notice and any statement of authorship are reproduced + # on all copies. Neither the Government nor the University makes + # any warranty, express or implied, or assumes any liability or + # responsibility for the use of this software. + # @(#)snmp.awk.x 1.1 (LANL) 1/15/90 + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-snmp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +/* + * Universal ASN.1 types + * (we only care about the tag values for those allowed in the Internet SMI) + */ +char *Universal[] = { + "U-0", + "Boolean", + "Integer", +#define INTEGER 2 + "Bitstring", + "String", +#define STRING 4 + "Null", +#define ASN_NULL 5 + "ObjID", +#define OBJECTID 6 + "ObjectDes", + "U-8","U-9","U-10","U-11", /* 8-11 */ + "U-12","U-13","U-14","U-15", /* 12-15 */ + "Sequence", +#define SEQUENCE 16 + "Set" +}; + +/* + * Application-wide ASN.1 types from the Internet SMI and their tags + */ +char *Application[] = { + "IpAddress", +#define IPADDR 0 + "Counter", +#define COUNTER 1 + "Gauge", +#define GAUGE 2 + "TimeTicks", +#define TIMETICKS 3 + "Opaque" +}; + +/* + * Context-specific ASN.1 types for the SNMP PDUs and their tags + */ +char *Context[] = { + "GetRequest", +#define GETREQ 0 + "GetNextRequest", +#define GETNEXTREQ 1 + "GetResponse", +#define GETRESP 2 + "SetRequest", +#define SETREQ 3 + "Trap" +#define TRAP 4 +}; + +/* + * Private ASN.1 types + * The Internet SMI does not specify any + */ +char *Private[] = { + "P-0" +}; + +/* + * error-status values for any SNMP PDU + */ +char *ErrorStatus[] = { + "noError", + "tooBig", + "noSuchName", + "badValue", + "readOnly", + "genErr" +}; +#define DECODE_ErrorStatus(e) \ + ( e >= 0 && e <= sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \ + ? ErrorStatus[e] : (sprintf(errbuf, "err=%u", e), errbuf)) + +/* + * generic-trap values in the SNMP Trap-PDU + */ +char *GenericTrap[] = { + "coldStart", + "warmStart", + "linkDown", + "linkUp", + "authenticationFailure", + "egpNeighborLoss", + "enterpriseSpecific" +#define GT_ENTERPRISE 7 +}; +#define DECODE_GenericTrap(t) \ + ( t >= 0 && t <= sizeof(GenericTrap)/sizeof(GenericTrap[0]) \ + ? GenericTrap[t] : (sprintf(buf, "gt=%d", t), buf)) + +/* + * ASN.1 type class table + * Ties together the preceding Universal, Application, Context, and Private + * type definitions. + */ +#define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */ +struct { + char *name; + char **Id; + int numIDs; + } Class[] = { + defineCLASS(Universal), +#define UNIVERSAL 0 + defineCLASS(Application), +#define APPLICATION 1 + defineCLASS(Context), +#define CONTEXT 2 + defineCLASS(Private), +#define PRIVATE 3 +}; + +/* + * defined forms for ASN.1 types + */ +char *Form[] = { + "Primitive", +#define PRIMITIVE 0 + "Constructed", +#define CONSTRUCTED 1 +}; + +/* + * A structure for the OID tree for the compiled-in MIB. + * This is stored as a general-order tree. + */ +struct obj { + char *desc; /* name of object */ + u_char oid; /* sub-id following parent */ + u_char type; /* object type (unused) */ + struct obj *child, *next; /* child and next sibling pointers */ +} *objp = NULL; + +/* + * Include the compiled in SNMP MIB. "mib.h" is produced by feeding + * RFC-1156 format files into "makemib". "mib.h" MUST define at least + * a value for `mibroot'. + * + * In particular, this is gross, as this is including initialized structures, + * and by right shouldn't be an "include" file. + */ +#include "mib.h" + +/* + * This defines a list of OIDs which will be abbreviated on output. + * Currently, this includes the prefixes for the Internet MIB, the + * private enterprises tree, and the experimental tree. + */ +struct obj_abrev { + char *prefix; /* prefix for this abrev */ + struct obj *node; /* pointer into object table */ + char *oid; /* ASN.1 encoded OID */ +} obj_abrev_list[] = { +#ifndef NO_ABREV_MIB + /* .iso.org.dod.internet.mgmt.mib */ + { "", &_mib_obj, "\53\6\1\2\1" }, +#endif +#ifndef NO_ABREV_ENTER + /* .iso.org.dod.internet.private.enterprises */ + { "E:", &_enterprises_obj, "\53\6\1\4\1" }, +#endif +#ifndef NO_ABREV_EXPERI + /* .iso.org.dod.internet.experimental */ + { "X:", &_experimental_obj, "\53\6\1\3" }, +#endif + { 0,0,0 } +}; + +/* + * This is used in the OID print routine to walk down the object tree + * rooted at `mibroot'. + */ +#define OBJ_PRINT(o, suppressdot) \ +{ \ + if (objp) { \ + do { \ + if ((o) == objp->oid) \ + break; \ + } while ((objp = objp->next) != NULL); \ + } \ + if (objp) { \ + printf(suppressdot?"%s":".%s", objp->desc); \ + objp = objp->child; \ + } else \ + printf(suppressdot?"%u":".%u", (o)); \ +} + +/* + * This is the definition for the Any-Data-Type storage used purely for + * temporary internal representation while decoding an ASN.1 data stream. + */ +struct be { + u_int32_t asnlen; + union { + caddr_t raw; + int32_t integer; + u_int32_t uns; + const u_char *str; + } data; + u_short id; + u_char form, class; /* tag info */ + u_char type; +#define BE_ANY 255 +#define BE_NONE 0 +#define BE_NULL 1 +#define BE_OCTET 2 +#define BE_OID 3 +#define BE_INT 4 +#define BE_UNS 5 +#define BE_STR 6 +#define BE_SEQ 7 +#define BE_INETADDR 8 +#define BE_PDU 9 +}; + +/* + * Defaults for SNMP PDU components + */ +#define DEF_COMMUNITY "public" +#define DEF_VERSION 0 + +/* + * constants for ASN.1 decoding + */ +#define OIDMUX 40 +#define ASNLEN_INETADDR 4 +#define ASN_SHIFT7 7 +#define ASN_SHIFT8 8 +#define ASN_BIT8 0x80 +#define ASN_LONGLEN 0x80 + +#define ASN_ID_BITS 0x1f +#define ASN_FORM_BITS 0x20 +#define ASN_FORM_SHIFT 5 +#define ASN_CLASS_BITS 0xc0 +#define ASN_CLASS_SHIFT 6 + +#define ASN_ID_EXT 0x1f /* extension ID in tag field */ + +/* + * truncated==1 means the packet was complete, but we don't have all of + * it to decode. + */ +static int truncated; +#define ifNotTruncated if (truncated) fputs("[|snmp]", stdout); else + +/* + * This decodes the next ASN.1 object in the stream pointed to by "p" + * (and of real-length "len") and stores the intermediate data in the + * provided BE object. + * + * This returns -l if it fails (i.e., the ASN.1 stream is not valid). + * O/w, this returns the number of bytes parsed from "p". + */ +static int +asn1_parse(register const u_char *p, u_int len, struct be *elem) +{ + u_char form, class, id; + int i, hdr; + + elem->asnlen = 0; + elem->type = BE_ANY; + if (len < 1) { + ifNotTruncated puts("[nothing to parse], stdout"); + return -1; + } + + /* + * it would be nice to use a bit field, but you can't depend on them. + * +---+---+---+---+---+---+---+---+ + * + class |frm| id | + * +---+---+---+---+---+---+---+---+ + * 7 6 5 4 3 2 1 0 + */ + id = *p & ASN_ID_BITS; /* lower 5 bits, range 00-1f */ +#ifdef notdef + form = (*p & 0xe0) >> 5; /* move upper 3 bits to lower 3 */ + class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */ + form &= 0x1; /* bit 5 -> bit 0, range 0-1 */ +#else + form = (u_char)(*p & ASN_FORM_BITS) >> ASN_FORM_SHIFT; + class = (u_char)(*p & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT; +#endif + elem->form = form; + elem->class = class; + elem->id = id; + if (vflag) + printf("|%.2x", *p); + p++; len--; hdr = 1; + /* extended tag field */ + if (id == ASN_ID_EXT) { + for (id = 0; *p & ASN_BIT8 && len > 0; len--, hdr++, p++) { + if (vflag) + printf("|%.2x", *p); + id = (id << 7) | (*p & ~ASN_BIT8); + } + if (len == 0 && *p & ASN_BIT8) { + ifNotTruncated fputs("[Xtagfield?]", stdout); + return -1; + } + elem->id = id = (id << 7) | *p; + --len; + ++hdr; + ++p; + } + if (len < 1) { + ifNotTruncated fputs("[no asnlen]", stdout); + return -1; + } + elem->asnlen = *p; + if (vflag) + printf("|%.2x", *p); + p++; len--; hdr++; + if (elem->asnlen & ASN_BIT8) { + int noct = elem->asnlen % ASN_BIT8; + elem->asnlen = 0; + if (len < noct) { + ifNotTruncated printf("[asnlen? %d<%d]", len, noct); + return -1; + } + for (; noct-- > 0; len--, hdr++) { + if (vflag) + printf("|%.2x", *p); + elem->asnlen = (elem->asnlen << ASN_SHIFT8) | *p++; + } + } + if (len < elem->asnlen) { + if (!truncated) { + printf("[len%dasnlen); + return -1; + } + /* maybe should check at least 4? */ + elem->asnlen = len; + } + if (form >= sizeof(Form)/sizeof(Form[0])) { + ifNotTruncated printf("[form?%d]", form); + return -1; + } + if (class >= sizeof(Class)/sizeof(Class[0])) { + ifNotTruncated printf("[class?%c/%d]", *Form[form], class); + return -1; + } + if ((int)id >= Class[class].numIDs) { + ifNotTruncated printf("[id?%c/%s/%d]", *Form[form], + Class[class].name, id); + return -1; + } + + switch (form) { + case PRIMITIVE: + switch (class) { + case UNIVERSAL: + switch (id) { + case STRING: + elem->type = BE_STR; + elem->data.str = p; + break; + + case INTEGER: { + register int32_t data; + elem->type = BE_INT; + data = 0; + + if (*p & ASN_BIT8) /* negative */ + data = -1; + for (i = elem->asnlen; i-- > 0; p++) + data = (data << ASN_SHIFT8) | *p; + elem->data.integer = data; + break; + } + + case OBJECTID: + elem->type = BE_OID; + elem->data.raw = (caddr_t)p; + break; + + case ASN_NULL: + elem->type = BE_NULL; + elem->data.raw = NULL; + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("[P/U/%s]", + Class[class].Id[id]); + break; + } + break; + + case APPLICATION: + switch (id) { + case IPADDR: + elem->type = BE_INETADDR; + elem->data.raw = (caddr_t)p; + break; + + case COUNTER: + case GAUGE: + case TIMETICKS: { + register u_int32_t data; + elem->type = BE_UNS; + data = 0; + for (i = elem->asnlen; i-- > 0; p++) + data = (data << 8) + *p; + elem->data.uns = data; + break; + } + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("[P/A/%s]", + Class[class].Id[id]); + break; + } + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("[P/%s/%s]", + Class[class].name, Class[class].Id[id]); + break; + } + break; + + case CONSTRUCTED: + switch (class) { + case UNIVERSAL: + switch (id) { + case SEQUENCE: + elem->type = BE_SEQ; + elem->data.raw = (caddr_t)p; + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("C/U/%s", Class[class].Id[id]); + break; + } + break; + + case CONTEXT: + elem->type = BE_PDU; + elem->data.raw = (caddr_t)p; + break; + + default: + elem->type = BE_OCTET; + elem->data.raw = (caddr_t)p; + printf("C/%s/%s", + Class[class].name, Class[class].Id[id]); + break; + } + break; + } + p += elem->asnlen; + len -= elem->asnlen; + return elem->asnlen + hdr; +} + +/* + * Display the ASN.1 object represented by the BE object. + * This used to be an integral part of asn1_parse() before the intermediate + * BE form was added. + */ +static void +asn1_print(struct be *elem) +{ + u_char *p = (u_char *)elem->data.raw; + u_int32_t asnlen = elem->asnlen; + int i; + + switch (elem->type) { + + case BE_OCTET: + for (i = asnlen; i-- > 0; p++); + printf("_%.2x", *p); + break; + + case BE_NULL: + break; + + case BE_OID: { + int o = 0, first = -1, i = asnlen; + + if (!nflag && asnlen > 2) { + struct obj_abrev *a = &obj_abrev_list[0]; + for (; a->node; a++) { + if (!memcmp(a->oid, (char *)p, + strlen(a->oid))) { + objp = a->node->child; + i -= strlen(a->oid); + p += strlen(a->oid); + fputs(a->prefix, stdout); + first = 1; + break; + } + } + } + for (; i-- > 0; p++) { + o = (o << ASN_SHIFT7) + (*p & ~ASN_BIT8); + if (*p & ASN_LONGLEN) + continue; + + /* + * first subitem encodes two items with 1st*OIDMUX+2nd + */ + if (first < 0) { + if (!nflag) + objp = mibroot; + first = 0; + OBJ_PRINT(o/OIDMUX, first); + o %= OIDMUX; + } + OBJ_PRINT(o, first); + if (--first < 0) + first = 0; + o = 0; + } + break; + } + + case BE_INT: + printf("%d", elem->data.integer); + break; + + case BE_UNS: + printf("%d", elem->data.uns); + break; + + case BE_STR: { + register int printable = 1, first = 1; + const u_char *p = elem->data.str; + for (i = asnlen; printable && i-- > 0; p++) + printable = isprint(*p) || isspace(*p); + p = elem->data.str; + if (printable) { + putchar('"'); + (void)fn_print(p, p + asnlen); + putchar('"'); + } else + for (i = asnlen; i-- > 0; p++) { + printf(first ? "%.2x" : "_%.2x", *p); + first = 0; + } + break; + } + + case BE_SEQ: + printf("Seq(%u)", elem->asnlen); + break; + + case BE_INETADDR: { + char sep; + if (asnlen != ASNLEN_INETADDR) + printf("[inetaddr len!=%d]", ASNLEN_INETADDR); + sep='['; + for (i = asnlen; i-- > 0; p++) { + printf("%c%u", sep, *p); + sep='.'; + } + putchar(']'); + break; + } + + case BE_PDU: + printf("%s(%u)", + Class[CONTEXT].Id[elem->id], elem->asnlen); + break; + + case BE_ANY: + fputs("[BE_ANY!?]", stdout); + break; + + default: + fputs("[be!?]", stdout); + break; + } +} + +#ifdef notdef +/* + * This is a brute force ASN.1 printer: recurses to dump an entire structure. + * This will work for any ASN.1 stream, not just an SNMP PDU. + * + * By adding newlines and spaces at the correct places, this would print in + * Rose-Normal-Form. + * + * This is not currently used. + */ +static void +asn1_decode(u_char *p, u_int length) +{ + struct be elem; + int i = 0; + + while (i >= 0 && length > 0) { + i = asn1_parse(p, length, &elem); + if (i >= 0) { + fputs(" ", stdout); + asn1_print(&elem); + if (elem.type == BE_SEQ || elem.type == BE_PDU) { + fputs(" {", stdout); + asn1_decode(elem.data.raw, elem.asnlen); + fputs(" }", stdout); + } + length -= i; + p += i; + } + } +} +#endif + +/* + * General SNMP header + * SEQUENCE { + * version INTEGER {version-1(0)}, + * community OCTET STRING, + * data ANY -- PDUs + * } + * PDUs for all but Trap: (see rfc1157 from page 15 on) + * SEQUENCE { + * request-id INTEGER, + * error-status INTEGER, + * error-index INTEGER, + * varbindlist SEQUENCE OF + * SEQUENCE { + * name ObjectName, + * value ObjectValue + * } + * } + * PDU for Trap: + * SEQUENCE { + * enterprise OBJECT IDENTIFIER, + * agent-addr NetworkAddress, + * generic-trap INTEGER, + * specific-trap INTEGER, + * time-stamp TimeTicks, + * varbindlist SEQUENCE OF + * SEQUENCE { + * name ObjectName, + * value ObjectValue + * } + * } + */ + +/* + * Decode SNMP varBind + */ +static void +varbind_print(u_char pduid, const u_char *np, u_int length, int error) +{ + struct be elem; + int count = 0, ind; + + /* Sequence of varBind */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_SEQ) { + fputs("[!SEQ of varbind]", stdout); + asn1_print(&elem); + return; + } + if (count < length) + printf("[%d extra after SEQ of varbind]", length - count); + /* descend */ + length = elem.asnlen; + np = (u_char *)elem.data.raw; + + for (ind = 1; length > 0; ind++) { + const u_char *vbend; + u_int vblength; + + if (!error || ind == error) + fputs(" ", stdout); + + /* Sequence */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_SEQ) { + fputs("[!varbind]", stdout); + asn1_print(&elem); + return; + } + vbend = np + count; + vblength = length - count; + /* descend */ + length = elem.asnlen; + np = (u_char *)elem.data.raw; + + /* objName (OID) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_OID) { + fputs("[objName!=OID]", stdout); + asn1_print(&elem); + return; + } + if (!error || ind == error) + asn1_print(&elem); + length -= count; + np += count; + + if (pduid != GETREQ && pduid != GETNEXTREQ && !error) + fputs("=", stdout); + + /* objVal (ANY) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (pduid == GETREQ || pduid == GETNEXTREQ) { + if (elem.type != BE_NULL) { + fputs("[objVal!=NULL]", stdout); + asn1_print(&elem); + } + } else + if (error && ind == error && elem.type != BE_NULL) + fputs("[err objVal!=NULL]", stdout); + if (!error || ind == error) + asn1_print(&elem); + + length = vblength; + np = vbend; + } +} + +/* + * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, and SetRequest + */ +static void +snmppdu_print(u_char pduid, const u_char *np, u_int length) +{ + struct be elem; + int count = 0, error; + + /* reqId (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[reqId!=INT]", stdout); + asn1_print(&elem); + return; + } + /* ignore the reqId */ + length -= count; + np += count; + + /* errorStatus (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[errorStatus!=INT]", stdout); + asn1_print(&elem); + return; + } + error = 0; + if ((pduid == GETREQ || pduid == GETNEXTREQ) + && elem.data.integer != 0) { + char errbuf[10]; + printf("[errorStatus(%s)!=0]", + DECODE_ErrorStatus(elem.data.integer)); + } else if (elem.data.integer != 0) { + char errbuf[10]; + printf(" %s", DECODE_ErrorStatus(elem.data.integer)); + error = elem.data.integer; + } + length -= count; + np += count; + + /* errorIndex (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[errorIndex!=INT]", stdout); + asn1_print(&elem); + return; + } + if ((pduid == GETREQ || pduid == GETNEXTREQ) + && elem.data.integer != 0) + printf("[errorIndex(%d)!=0]", elem.data.integer); + else if (elem.data.integer != 0) { + if (!error) + printf("[errorIndex(%d) w/o errorStatus]", + elem.data.integer); + else { + printf("@%d", elem.data.integer); + error = elem.data.integer; + } + } else if (error) { + fputs("[errorIndex==0]", stdout); + error = 0; + } + length -= count; + np += count; + + varbind_print(pduid, np, length, error); + return; +} + +/* + * Decode SNMP Trap PDU + */ +static void +trap_print(const u_char *np, u_int length) +{ + struct be elem; + int count = 0, generic; + + putchar(' '); + + /* enterprise (oid) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_OID) { + fputs("[enterprise!=OID]", stdout); + asn1_print(&elem); + return; + } + asn1_print(&elem); + length -= count; + np += count; + + putchar(' '); + + /* agent-addr (inetaddr) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INETADDR) { + fputs("[agent-addr!=INETADDR]", stdout); + asn1_print(&elem); + return; + } + asn1_print(&elem); + length -= count; + np += count; + + /* generic-trap (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[generic-trap!=INT]", stdout); + asn1_print(&elem); + return; + } + generic = elem.data.integer; + { + char buf[10]; + printf(" %s", DECODE_GenericTrap(generic)); + } + length -= count; + np += count; + + /* specific-trap (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[specific-trap!=INT]", stdout); + asn1_print(&elem); + return; + } + if (generic != GT_ENTERPRISE) { + if (elem.data.integer != 0) + printf("[specific-trap(%d)!=0]", elem.data.integer); + } else + printf(" s=%d", elem.data.integer); + length -= count; + np += count; + + putchar(' '); + + /* time-stamp (TimeTicks) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_UNS) { /* XXX */ + fputs("[time-stamp!=TIMETICKS]", stdout); + asn1_print(&elem); + return; + } + asn1_print(&elem); + length -= count; + np += count; + + varbind_print (TRAP, np, length, 0); + return; +} + +/* + * Decode SNMP header and pass on to PDU printing routines + */ +void +snmp_print(const u_char *np, u_int length) +{ + struct be elem, pdu; + int count = 0; + + truncated = 0; + + /* truncated packet? */ + if (np + length > snapend) { + truncated = 1; + length = snapend - np; + } + + putchar(' '); + + /* initial Sequence */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_SEQ) { + fputs("[!init SEQ]", stdout); + asn1_print(&elem); + return; + } + if (count < length) + printf("[%d extra after iSEQ]", length - count); + /* descend */ + length = elem.asnlen; + np = (u_char *)elem.data.raw; + /* Version (Integer) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_INT) { + fputs("[version!=INT]", stdout); + asn1_print(&elem); + return; + } + /* only handle version==0 */ + if (elem.data.integer != DEF_VERSION) { + printf("[version(%d)!=0]", elem.data.integer); + return; + } + length -= count; + np += count; + + /* Community (String) */ + if ((count = asn1_parse(np, length, &elem)) < 0) + return; + if (elem.type != BE_STR) { + fputs("[comm!=STR]", stdout); + asn1_print(&elem); + return; + } + /* default community */ + if (strncmp((char *)elem.data.str, DEF_COMMUNITY, + sizeof(DEF_COMMUNITY) - 1)) + /* ! "public" */ + printf("C=%.*s ", (int)elem.asnlen, elem.data.str); + length -= count; + np += count; + + /* PDU (Context) */ + if ((count = asn1_parse(np, length, &pdu)) < 0) + return; + if (pdu.type != BE_PDU) { + fputs("[no PDU]", stdout); + return; + } + if (count < length) + printf("[%d extra after PDU]", length - count); + asn1_print(&pdu); + /* descend into PDU */ + length = pdu.asnlen; + np = (u_char *)pdu.data.raw; + + switch (pdu.id) { + case TRAP: + trap_print(np, length); + break; + case GETREQ: + case GETNEXTREQ: + case GETRESP: + case SETREQ: + snmppdu_print(pdu.id, np, length); + break; + } + return; +} diff --git a/tcpdump.tproj/print-sunrpc.c b/tcpdump.tproj/print-sunrpc.c new file mode 100644 index 0000000..0c9f696 --- /dev/null +++ b/tcpdump.tproj/print-sunrpc.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-sunrpc.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#if __STDC__ +struct mbuf; +struct rtentry; +#endif +#include + +#include +#include +#include +#include +#include + +#include +#ifdef HAVE_RPC_RPCENT_H +#include +#endif +#include + +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +static struct tok proc2str[] = { + { PMAPPROC_NULL, "null" }, + { PMAPPROC_SET, "set" }, + { PMAPPROC_UNSET, "unset" }, + { PMAPPROC_GETPORT, "getport" }, + { PMAPPROC_DUMP, "dump" }, + { PMAPPROC_CALLIT, "call" }, + { 0, NULL } +}; + +/* Forwards */ +static char *progstr(u_int32_t); + +void +sunrpcrequest_print(register const u_char *bp, register u_int length, + register const u_char *bp2) +{ + register const struct rpc_msg *rp; + register const struct ip *ip; + u_int32_t x; + + rp = (struct rpc_msg *)bp; + ip = (struct ip *)bp2; + + if (!nflag) + (void)printf("%s.%x > %s.sunrpc: %d", + ipaddr_string(&ip->ip_src), + (u_int32_t)ntohl(rp->rm_xid), + ipaddr_string(&ip->ip_dst), + length); + else + (void)printf("%s.%x > %s.%x: %d", + ipaddr_string(&ip->ip_src), + (u_int32_t)ntohl(rp->rm_xid), + ipaddr_string(&ip->ip_dst), + PMAPPORT, + length); + printf(" %s", tok2str(proc2str, " proc #%u", + (u_int32_t)ntohl(rp->rm_call.cb_proc))); + x = ntohl(rp->rm_call.cb_rpcvers); + if (x != 2) + printf(" [rpcver %u]", x); + + switch (ntohl(rp->rm_call.cb_proc)) { + + case PMAPPROC_SET: + case PMAPPROC_UNSET: + case PMAPPROC_GETPORT: + case PMAPPROC_CALLIT: + x = ntohl(rp->rm_call.cb_prog); + if (!nflag) + printf(" %s", progstr(x)); + else + printf(" %u", x); + printf(".%u", (u_int32_t)ntohl(rp->rm_call.cb_vers)); + break; + } +} + +static char * +progstr(prog) + u_int32_t prog; +{ + register struct rpcent *rp; + static char buf[32]; + static lastprog = 0; + + if (lastprog != 0 && prog == lastprog) + return (buf); + rp = getrpcbynumber(prog); + if (rp == NULL) + (void) sprintf(buf, "#%u", prog); + else + strcpy(buf, rp->r_name); + return (buf); +} diff --git a/tcpdump.tproj/print-tcp.c b/tcpdump.tproj/print-tcp.c new file mode 100644 index 0000000..2c0d1e3 --- /dev/null +++ b/tcpdump.tproj/print-tcp.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-tcp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "extract.h" + +/* Compatibility */ +#ifndef TCPOPT_WSCALE +#define TCPOPT_WSCALE 3 /* window scale factor (rfc1072) */ +#endif +#ifndef TCPOPT_SACKOK +#define TCPOPT_SACKOK 4 /* selective ack ok (rfc1072) */ +#endif +#ifndef TCPOPT_SACK +#define TCPOPT_SACK 5 /* selective ack (rfc1072) */ +#endif +#ifndef TCPOPT_ECHO +#define TCPOPT_ECHO 6 /* echo (rfc1072) */ +#endif +#ifndef TCPOPT_ECHOREPLY +#define TCPOPT_ECHOREPLY 7 /* echo (rfc1072) */ +#endif +#ifndef TCPOPT_TIMESTAMP +#define TCPOPT_TIMESTAMP 8 /* timestamps (rfc1323) */ +#endif +#ifndef TCPOPT_CC +#define TCPOPT_CC 11 /* T/TCP CC options (rfc1644) */ +#endif +#ifndef TCPOPT_CCNEW +#define TCPOPT_CCNEW 12 /* T/TCP CC options (rfc1644) */ +#endif +#ifndef TCPOPT_CCECHO +#define TCPOPT_CCECHO 13 /* T/TCP CC options (rfc1644) */ +#endif + +struct tha { + struct in_addr src; + struct in_addr dst; + u_int port; +}; + +struct tcp_seq_hash { + struct tcp_seq_hash *nxt; + struct tha addr; + tcp_seq seq; + tcp_seq ack; +}; + +#define TSEQ_HASHSIZE 919 + +/* These tcp optinos do not have the size octet */ +#define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP) + +static struct tcp_seq_hash tcp_seq_hash[TSEQ_HASHSIZE]; + + +void +tcp_print(register const u_char *bp, register u_int length, + register const u_char *bp2) +{ + register const struct tcphdr *tp; + register const struct ip *ip; + register u_char flags; + register int hlen; + register char ch; + u_short sport, dport, win, urp; + u_int32_t seq, ack; + + tp = (struct tcphdr *)bp; + ip = (struct ip *)bp2; + ch = '\0'; + TCHECK(*tp); + if (length < sizeof(*tp)) { + (void)printf("truncated-tcp %d", length); + return; + } + + sport = ntohs(tp->th_sport); + dport = ntohs(tp->th_dport); + seq = ntohl(tp->th_seq); + ack = ntohl(tp->th_ack); + win = ntohs(tp->th_win); + urp = ntohs(tp->th_urp); + + (void)printf("%s.%s > %s.%s: ", + ipaddr_string(&ip->ip_src), tcpport_string(sport), + ipaddr_string(&ip->ip_dst), tcpport_string(dport)); + + if (qflag) { + (void)printf("tcp %d", length - tp->th_off * 4); + return; + } + if ((flags = tp->th_flags) & (TH_SYN|TH_FIN|TH_RST|TH_PUSH)) { + if (flags & TH_SYN) + putchar('S'); + if (flags & TH_FIN) + putchar('F'); + if (flags & TH_RST) + putchar('R'); + if (flags & TH_PUSH) + putchar('P'); + } else + putchar('.'); + + if (!Sflag && (flags & TH_ACK)) { + register struct tcp_seq_hash *th; + register int rev; + struct tha tha; + /* + * Find (or record) the initial sequence numbers for + * this conversation. (we pick an arbitrary + * collating order so there's only one entry for + * both directions). + */ + if (sport < dport || + (sport == dport && + ip->ip_src.s_addr < ip->ip_dst.s_addr)) { + tha.src = ip->ip_src, tha.dst = ip->ip_dst; + tha.port = sport << 16 | dport; + rev = 0; + } else { + tha.src = ip->ip_dst, tha.dst = ip->ip_src; + tha.port = dport << 16 | sport; + rev = 1; + } + + for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; + th->nxt; th = th->nxt) + if (!memcmp((char *)&tha, (char *)&th->addr, + sizeof(th->addr))) + break; + + if (!th->nxt || flags & TH_SYN) { + /* didn't find it or new conversation */ + if (th->nxt == NULL) { + th->nxt = (struct tcp_seq_hash *) + calloc(1, sizeof(*th)); + if (th->nxt == NULL) + error("tcp_print: calloc"); + } + th->addr = tha; + if (rev) + th->ack = seq, th->seq = ack - 1; + else + th->seq = seq, th->ack = ack - 1; + } else { + if (rev) + seq -= th->ack, ack -= th->seq; + else + seq -= th->seq, ack -= th->ack; + } + } + hlen = tp->th_off * 4; + if (hlen > length) { + (void)printf(" [bad hdr length]"); + return; + } + length -= hlen; + if (length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) + (void)printf(" %u:%u(%d)", seq, seq + length, length); + if (flags & TH_ACK) + (void)printf(" ack %u", ack); + + (void)printf(" win %d", win); + + if (flags & TH_URG) + (void)printf(" urg %d", urp); + /* + * Handle any options. + */ + if ((hlen -= sizeof(*tp)) > 0) { + register const u_char *cp; + register int i, opt, len, datalen; + + cp = (const u_char *)tp + sizeof(*tp); + putchar(' '); + ch = '<'; + while (hlen > 0) { + putchar(ch); + TCHECK(*cp); + opt = *cp++; + if (ZEROLENOPT(opt)) + len = 1; + else { + TCHECK(*cp); + len = *cp++; /* total including type, len */ + if (len < 2 || len > hlen) + goto bad; + --hlen; /* account for length byte */ + } + --hlen; /* account for type byte */ + datalen = 0; + +/* Bail if "l" bytes of data are not left or were not captured */ +#define LENCHECK(l) { if ((l) > hlen) goto bad; TCHECK2(*cp, l); } + + switch (opt) { + + case TCPOPT_MAXSEG: + (void)printf("mss"); + datalen = 2; + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_16BITS(cp)); + + break; + + case TCPOPT_EOL: + (void)printf("eol"); + break; + + case TCPOPT_NOP: + (void)printf("nop"); + break; + + case TCPOPT_WSCALE: + (void)printf("wscale"); + datalen = 1; + LENCHECK(datalen); + (void)printf(" %u", *cp); + break; + + case TCPOPT_SACKOK: + (void)printf("sackOK"); + break; + + case TCPOPT_SACK: + (void)printf("sack"); + datalen = len - 2; + for (i = 0; i < datalen; i += 4) { + LENCHECK(i + 4); + /* block-size@relative-origin */ + (void)printf(" %u@%u", + EXTRACT_16BITS(cp + i + 2), + EXTRACT_16BITS(cp + i)); + } + if (datalen % 4) + (void)printf("[len %d]", len); + break; + + case TCPOPT_ECHO: + (void)printf("echo"); + datalen = 4; + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_32BITS(cp)); + break; + + case TCPOPT_ECHOREPLY: + (void)printf("echoreply"); + datalen = 4; + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_32BITS(cp)); + break; + + case TCPOPT_TIMESTAMP: + (void)printf("timestamp"); + datalen = 8; + LENCHECK(4); + (void)printf(" %u", EXTRACT_32BITS(cp)); + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_32BITS(cp + 4)); + break; + + case TCPOPT_CC: + (void)printf("cc"); + datalen = 4; + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_32BITS(cp)); + break; + + case TCPOPT_CCNEW: + (void)printf("ccnew"); + datalen = 4; + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_32BITS(cp)); + break; + + case TCPOPT_CCECHO: + (void)printf("ccecho"); + datalen = 4; + LENCHECK(datalen); + (void)printf(" %u", EXTRACT_32BITS(cp)); + break; + + default: + (void)printf("opt-%d:", opt); + datalen = len - 2; + for (i = 0; i < datalen; ++i) { + LENCHECK(i); + (void)printf("%02x", cp[i]); + } + break; + } + + /* Account for data printed */ + cp += datalen; + hlen -= datalen; + + /* Check specification against observed length */ + ++datalen; /* option octet */ + if (!ZEROLENOPT(opt)) + ++datalen; /* size octet */ + if (datalen != len) + (void)printf("[len %d]", len); + ch = ','; + if (opt == TCPOPT_EOL) + break; + } + putchar('>'); + } + return; +bad: + fputs("[bad opt]", stdout); + if (ch != '\0') + putchar('>'); + return; +trunc: + fputs("[|tcp]", stdout); + if (ch != '\0') + putchar('>'); +} + diff --git a/tcpdump.tproj/print-tftp.c b/tcpdump.tproj/print-tftp.c new file mode 100644 index 0000000..9db5775 --- /dev/null +++ b/tcpdump.tproj/print-tftp.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * Format and print trivial file transfer protocol packets. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-tftp.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include + +#include + +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" + +/* op code to string mapping */ +static struct tok op2str[] = { + { RRQ, "RRQ" }, /* read request */ + { WRQ, "WRQ" }, /* write request */ + { DATA, "DATA" }, /* data packet */ + { ACK, "ACK" }, /* acknowledgement */ + { ERROR, "ERROR" }, /* error code */ + { 0, NULL } +}; + +/* error code to string mapping */ +static struct tok err2str[] = { + { EUNDEF, "EUNDEF" }, /* not defined */ + { ENOTFOUND, "ENOTFOUND" }, /* file not found */ + { EACCESS, "EACCESS" }, /* access violation */ + { ENOSPACE, "ENOSPACE" }, /* disk full or allocation exceeded */ + { EBADOP, "EBADOP" }, /* illegal TFTP operation */ + { EBADID, "EBADID" }, /* unknown transfer ID */ + { EEXISTS, "EEXISTS" }, /* file already exists */ + { ENOUSER, "ENOUSER" }, /* no such user */ + { 0, NULL } +}; + +/* + * Print trivial file transfer program requests + */ +void +tftp_print(register const u_char *bp, u_int length) +{ + register const struct tftphdr *tp; + register const char *cp; + register const u_char *p; + register int opcode, i; + static char tstr[] = " [|tftp]"; + + tp = (const struct tftphdr *)bp; + + /* Print length */ + printf(" %d", length); + + /* Print tftp request type */ + TCHECK(tp->th_opcode); + opcode = ntohs(tp->th_opcode); + cp = tok2str(op2str, "tftp-#%d", opcode); + printf(" %s", cp); + /* Bail if bogus opcode */ + if (*cp == 't') + return; + + switch (opcode) { + + case RRQ: + case WRQ: + /* + * XXX Not all arpa/tftp.h's specify th_stuff as any + * array; use address of th_block instead + */ +#ifdef notdef + p = (u_char *)tp->th_stuff; +#else + p = (u_char *)&tp->th_block; +#endif + fputs(" \"", stdout); + i = fn_print(p, snapend); + putchar('"'); + if (i) + goto trunc; + break; + + case ACK: + case DATA: + TCHECK(tp->th_block); + printf(" block %d", ntohs(tp->th_block)); + break; + + case ERROR: + /* Print error code string */ + TCHECK(tp->th_code); + printf(" %s ", tok2str(err2str, "tftp-err-#%d \"", + ntohs(tp->th_code))); + /* Print error message string */ + i = fn_print((const u_char *)tp->th_data, snapend); + putchar('"'); + if (i) + goto trunc; + break; + + default: + /* We shouldn't get here */ + printf("(unknown #%d)", opcode); + break; + } + return; +trunc: + fputs(tstr, stdout); + return; +} diff --git a/tcpdump.tproj/print-udp.c b/tcpdump.tproj/print-udp.c new file mode 100644 index 0000000..f8e4366 --- /dev/null +++ b/tcpdump.tproj/print-udp.c @@ -0,0 +1,464 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-udp.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef NOERROR /* Solaris sucks */ +#undef T_UNSPEC /* SINIX does too */ +#include +#include + +#include + +#include + +#include "interface.h" +#include "addrtoname.h" +#include "appletalk.h" + +#include "nfsv2.h" +#include "bootp.h" + +struct rtcphdr { + u_short rh_flags; /* T:2 P:1 CNT:5 PT:8 */ + u_short rh_len; /* length of message (in words) */ + u_int rh_ssrc; /* synchronization src id */ +}; + +typedef struct { + u_int upper; /* more significant 32 bits */ + u_int lower; /* less significant 32 bits */ +} ntp64; + +/* + * Sender report. + */ +struct rtcp_sr { + ntp64 sr_ntp; /* 64-bit ntp timestamp */ + u_int sr_ts; /* reference media timestamp */ + u_int sr_np; /* no. packets sent */ + u_int sr_nb; /* no. bytes sent */ +}; + +/* + * Receiver report. + * Time stamps are middle 32-bits of ntp timestamp. + */ +struct rtcp_rr { + u_int rr_srcid; /* sender being reported */ + u_int rr_nl; /* no. packets lost */ + u_int rr_ls; /* extended last seq number received */ + u_int rr_dv; /* jitter (delay variance) */ + u_int rr_lsr; /* orig. ts from last rr from this src */ + u_int rr_dlsr; /* time from recpt of last rr to xmit time */ +}; + +/*XXX*/ +#define RTCP_PT_SR 200 +#define RTCP_PT_RR 201 +#define RTCP_PT_SDES 202 +#define RTCP_SDES_CNAME 1 +#define RTCP_SDES_NAME 2 +#define RTCP_SDES_EMAIL 3 +#define RTCP_SDES_PHONE 4 +#define RTCP_SDES_LOC 5 +#define RTCP_SDES_TOOL 6 +#define RTCP_SDES_NOTE 7 +#define RTCP_SDES_PRIV 8 +#define RTCP_PT_BYE 203 +#define RTCP_PT_APP 204 + +static void +vat_print(const void *hdr, u_int len, register const struct udphdr *up) +{ + /* vat/vt audio */ + u_int ts = *(u_short *)hdr; + if ((ts & 0xf060) != 0) { + /* probably vt */ + (void)printf(" udp/vt %u %d / %d", + (u_int32_t)(ntohs(up->uh_ulen) - sizeof(*up)), + ts & 0x3ff, ts >> 10); + } else { + /* probably vat */ + u_int i0 = ntohl(((u_int *)hdr)[0]); + u_int i1 = ntohl(((u_int *)hdr)[1]); + printf(" udp/vat %u c%d %u%s", + (u_int32_t)(ntohs(up->uh_ulen) - sizeof(*up) - 8), + i0 & 0xffff, + i1, i0 & 0x800000? "*" : ""); + /* audio format */ + if (i0 & 0x1f0000) + printf(" f%d", (i0 >> 16) & 0x1f); + if (i0 & 0x3f000000) + printf(" s%d", (i0 >> 24) & 0x3f); + } +} + +static void +rtp_print(const void *hdr, u_int len, register const struct udphdr *up) +{ + /* rtp v1 or v2 */ + u_int *ip = (u_int *)hdr; + u_int hasopt, hasext, contype, hasmarker; + u_int i0 = ntohl(((u_int *)hdr)[0]); + u_int i1 = ntohl(((u_int *)hdr)[1]); + u_int dlen = ntohs(up->uh_ulen) - sizeof(*up) - 8; + const char * ptype; + + ip += 2; + len >>= 2; + len -= 2; + hasopt = 0; + hasext = 0; + if ((i0 >> 30) == 1) { + /* rtp v1 */ + hasopt = i0 & 0x800000; + contype = (i0 >> 16) & 0x3f; + hasmarker = i0 & 0x400000; + ptype = "rtpv1"; + } else { + /* rtp v2 */ + hasext = i0 & 0x10000000; + contype = (i0 >> 16) & 0x7f; + hasmarker = i0 & 0x800000; + dlen -= 4; + ptype = "rtp"; + ip += 1; + len -= 1; + } + printf(" udp/%s %d c%d %s%s %d %u", + ptype, + dlen, + contype, + (hasopt || hasext)? "+" : "", + hasmarker? "*" : "", + i0 & 0xffff, + i1); + if (vflag) { + printf(" %u", i1); + if (hasopt) { + u_int i2, optlen; + do { + i2 = ip[0]; + optlen = (i2 >> 16) & 0xff; + if (optlen == 0 || optlen > len) { + printf(" !opt"); + return; + } + ip += optlen; + len -= optlen; + } while ((int)i2 >= 0); + } + if (hasext) { + u_int i2, extlen; + i2 = ip[0]; + extlen = (i2 & 0xffff) + 1; + if (extlen > len) { + printf(" !ext"); + return; + } + ip += extlen; + } + if (contype == 0x1f) /*XXX H.261 */ + printf(" 0x%04x", ip[0] >> 16); + } +} + +static const u_char * +rtcp_print(const u_char *hdr, const u_char *ep) +{ + /* rtp v2 control (rtcp) */ + struct rtcp_rr *rr = 0; + struct rtcp_sr *sr; + struct rtcphdr *rh = (struct rtcphdr *)hdr; + u_int len; + u_short flags; + int cnt; + double ts, dts; + if ((u_char *)(rh + 1) > ep) { + printf(" [|rtcp]"); + return (ep); + } + len = (ntohs(rh->rh_len) + 1) * 4; + flags = ntohs(rh->rh_flags); + cnt = (flags >> 8) & 0x1f; + switch (flags & 0xff) { + case RTCP_PT_SR: + sr = (struct rtcp_sr *)(rh + 1); + printf(" sr"); + if (len != cnt * sizeof(*rr) + sizeof(*sr) + sizeof(*rh)) + printf(" [%d]", len); + if (vflag) + printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc)); + if ((u_char *)(sr + 1) > ep) { + printf(" [|rtcp]"); + return (ep); + } + ts = (double)((u_int32_t)ntohl(sr->sr_ntp.upper)) + + ((double)((u_int32_t)ntohl(sr->sr_ntp.lower)) / + 4294967296.0); + printf(" @%.2f %u %up %ub", ts, (u_int32_t)ntohl(sr->sr_ts), + (u_int32_t)ntohl(sr->sr_np), (u_int32_t)ntohl(sr->sr_nb)); + rr = (struct rtcp_rr *)(sr + 1); + break; + case RTCP_PT_RR: + printf(" rr"); + if (len != cnt * sizeof(*rr) + sizeof(*rh)) + printf(" [%d]", len); + rr = (struct rtcp_rr *)(rh + 1); + if (vflag) + printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc)); + break; + case RTCP_PT_SDES: + printf(" sdes %d", len); + if (vflag) + printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc)); + cnt = 0; + break; + case RTCP_PT_BYE: + printf(" bye %d", len); + if (vflag) + printf(" %u", (u_int32_t)ntohl(rh->rh_ssrc)); + cnt = 0; + break; + default: + printf(" type-0x%x %d", flags & 0xff, len); + cnt = 0; + break; + } + if (cnt > 1) + printf(" c%d", cnt); + while (--cnt >= 0) { + if ((u_char *)(rr + 1) > ep) { + printf(" [|rtcp]"); + return (ep); + } + if (vflag) + printf(" %u", (u_int32_t)ntohl(rr->rr_srcid)); + ts = (double)((u_int32_t)ntohl(rr->rr_lsr)) / 65536.; + dts = (double)((u_int32_t)ntohl(rr->rr_dlsr)) / 65536.; + printf(" %ul %us %uj @%.2f+%.2f", + (u_int32_t)ntohl(rr->rr_nl) & 0x00ffffff, + (u_int32_t)ntohl(rr->rr_ls), + (u_int32_t)ntohl(rr->rr_dv), ts, dts); + } + return (hdr + len); +} + +/* XXX probably should use getservbyname() and cache answers */ +#define TFTP_PORT 69 /*XXX*/ +#define KERBEROS_PORT 88 /*XXX*/ +#define SUNRPC_PORT 111 /*XXX*/ +#define SNMP_PORT 161 /*XXX*/ +#define NTP_PORT 123 /*XXX*/ +#define SNMPTRAP_PORT 162 /*XXX*/ +#define RIP_PORT 520 /*XXX*/ +#define KERBEROS_SEC_PORT 750 /*XXX*/ + +void +udp_print(register const u_char *bp, u_int length, register const u_char *bp2) +{ + register const struct udphdr *up; + register const struct ip *ip; + register const u_char *cp; + register const u_char *ep = bp + length; + u_short sport, dport, ulen; + + if (ep > snapend) + ep = snapend; + up = (struct udphdr *)bp; + ip = (struct ip *)bp2; + cp = (u_char *)(up + 1); + if (cp > snapend) { + printf("[|udp]"); + return; + } + if (length < sizeof(struct udphdr)) { + (void)printf(" truncated-udp %d", length); + return; + } + length -= sizeof(struct udphdr); + + sport = ntohs(up->uh_sport); + dport = ntohs(up->uh_dport); + ulen = ntohs(up->uh_ulen); + if (packettype) { + register struct rpc_msg *rp; + enum msg_type direction; + + switch (packettype) { + + case PT_VAT: + (void)printf("%s.%s > %s.%s:", + ipaddr_string(&ip->ip_src), + udpport_string(sport), + ipaddr_string(&ip->ip_dst), + udpport_string(dport)); + vat_print((void *)(up + 1), length, up); + break; + + case PT_WB: + (void)printf("%s.%s > %s.%s:", + ipaddr_string(&ip->ip_src), + udpport_string(sport), + ipaddr_string(&ip->ip_dst), + udpport_string(dport)); + wb_print((void *)(up + 1), length); + break; + + case PT_RPC: + rp = (struct rpc_msg *)(up + 1); + direction = (enum msg_type)ntohl(rp->rm_direction); + if (direction == CALL) + sunrpcrequest_print((u_char *)rp, length, + (u_char *)ip); + else + nfsreply_print((u_char *)rp, length, + (u_char *)ip); /*XXX*/ + break; + + case PT_RTP: + (void)printf("%s.%s > %s.%s:", + ipaddr_string(&ip->ip_src), + udpport_string(sport), + ipaddr_string(&ip->ip_dst), + udpport_string(dport)); + rtp_print((void *)(up + 1), length, up); + break; + + case PT_RTCP: + (void)printf("%s.%s > %s.%s:", + ipaddr_string(&ip->ip_src), + udpport_string(sport), + ipaddr_string(&ip->ip_dst), + udpport_string(dport)); + while (cp < ep) + cp = rtcp_print(cp, ep); + break; + } + return; + } + + if (!qflag) { + register struct rpc_msg *rp; + enum msg_type direction; + + rp = (struct rpc_msg *)(up + 1); + if (TTEST(rp->rm_direction)) { + direction = (enum msg_type)ntohl(rp->rm_direction); + if (dport == NFS_PORT && direction == CALL) { + nfsreq_print((u_char *)rp, length, + (u_char *)ip); + return; + } + if (sport == NFS_PORT && direction == REPLY) { + nfsreply_print((u_char *)rp, length, + (u_char *)ip); + return; + } +#ifdef notdef + if (dport == SUNRPC_PORT && direction == CALL) { + sunrpcrequest_print((u_char *)rp, length, (u_char *)ip); + return; + } +#endif + } + if (TTEST(((struct LAP *)cp)->type) && + ((struct LAP *)cp)->type == lapDDP && + (atalk_port(sport) || atalk_port(dport))) { + if (vflag) + fputs("kip ", stdout); + atalk_print(cp, length); + return; + } + } + (void)printf("%s.%s > %s.%s:", + ipaddr_string(&ip->ip_src), udpport_string(sport), + ipaddr_string(&ip->ip_dst), udpport_string(dport)); + + if (!qflag) { +#define ISPORT(p) (dport == (p) || sport == (p)) + if (ISPORT(NAMESERVER_PORT)) + ns_print((const u_char *)(up + 1), length); + else if (ISPORT(TFTP_PORT)) + tftp_print((const u_char *)(up + 1), length); + else if (ISPORT(IPPORT_BOOTPC) || ISPORT(IPPORT_BOOTPS)) + bootp_print((const u_char *)(up + 1), length, + sport, dport); + else if (ISPORT(RIP_PORT)) + rip_print((const u_char *)(up + 1), length); + else if (ISPORT(SNMP_PORT) || ISPORT(SNMPTRAP_PORT)) + snmp_print((const u_char *)(up + 1), length); + else if (ISPORT(NTP_PORT)) + ntp_print((const u_char *)(up + 1), length); + else if (ISPORT(KERBEROS_PORT) || ISPORT(KERBEROS_SEC_PORT)) + krb_print((const void *)(up + 1), length); + else if (dport == 3456) + vat_print((const void *)(up + 1), length, up); + /* + * Kludge in test for whiteboard packets. + */ + else if (dport == 4567) + wb_print((const void *)(up + 1), length); + else + (void)printf(" udp %u", + (u_int32_t)(ulen - sizeof(*up))); +#undef ISPORT + } else + (void)printf(" udp %u", (u_int32_t)(ulen - sizeof(*up))); +} diff --git a/tcpdump.tproj/print-wb.c b/tcpdump.tproj/print-wb.c new file mode 100644 index 0000000..3b0c160 --- /dev/null +++ b/tcpdump.tproj/print-wb.c @@ -0,0 +1,456 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/print-wb.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)"; +#endif + +#include +#include + +#include + +#include + +#include "interface.h" +#include "addrtoname.h" + +/* XXX need to add byte-swapping macros! */ + +/* + * Largest packet size. Everything should fit within this space. + * For instance, multiline objects are sent piecewise. + */ +#define MAXFRAMESIZE 1024 + +/* + * Multiple drawing ops can be sent in one packet. Each one starts on a + * an even multiple of DOP_ALIGN bytes, which must be a power of two. + */ +#define DOP_ALIGN 4 +#define DOP_ROUNDUP(x) ((((int)(x)) + (DOP_ALIGN - 1)) & ~(DOP_ALIGN - 1)) +#define DOP_NEXT(d)\ + ((struct dophdr *)((u_char *)(d) + \ + DOP_ROUNDUP(ntohs((d)->dh_len) + sizeof(*(d))))) + +/* + * Format of the whiteboard packet header. + * The transport level header. + */ +struct pkt_hdr { + u_int32_t ph_src; /* site id of source */ + u_int32_t ph_ts; /* time stamp (for skew computation) */ + u_short ph_version; /* version number */ + u_char ph_type; /* message type */ + u_char ph_flags; /* message flags */ +}; + +/* Packet types */ +#define PT_DRAWOP 0 /* drawing operation */ +#define PT_ID 1 /* announcement packet */ +#define PT_RREQ 2 /* repair request */ +#define PT_RREP 3 /* repair reply */ +#define PT_KILL 4 /* terminate participation */ +#define PT_PREQ 5 /* page vector request */ +#define PT_PREP 7 /* page vector reply */ + +/* flags */ +#define PF_USER 0x01 /* hint that packet has interactive data */ +#define PF_VIS 0x02 /* only visible ops wanted */ + +struct PageID { + u_int32_t p_sid; /* session id of initiator */ + u_int32_t p_uid; /* page number */ +}; + +struct dophdr { + u_int32_t dh_ts; /* sender's timestamp */ + u_short dh_len; /* body length */ + u_char dh_flags; + u_char dh_type; /* body type */ + /* body follows */ +}; +/* + * Drawing op sub-types. + */ +#define DT_RECT 2 +#define DT_LINE 3 +#define DT_ML 4 +#define DT_DEL 5 +#define DT_XFORM 6 +#define DT_ELL 7 +#define DT_CHAR 8 +#define DT_STR 9 +#define DT_NOP 10 +#define DT_PSCODE 11 +#define DT_PSCOMP 12 +#define DT_REF 13 +#define DT_SKIP 14 +#define DT_HOLE 15 +#define DT_MAXTYPE 15 + +/* + * A drawing operation. + */ +struct pkt_dop { + struct PageID pd_page; /* page that operations apply to */ + u_int32_t pd_sseq; /* start sequence number */ + u_int32_t pd_eseq; /* end sequence number */ + /* drawing ops follow */ +}; + +/* + * A repair request. + */ +struct pkt_rreq { + u_int32_t pr_id; /* source id of drawops to be repaired */ + struct PageID pr_page; /* page of drawops */ + u_int32_t pr_sseq; /* start seqno */ + u_int32_t pr_eseq; /* end seqno */ +}; + +/* + * A repair reply. + */ +struct pkt_rrep { + u_int32_t pr_id; /* original site id of ops */ + struct pkt_dop pr_dop; + /* drawing ops follow */ +}; + +struct id_off { + u_int32_t id; + u_int32_t off; +}; + +struct pgstate { + u_int32_t slot; + struct PageID page; + u_short nid; + u_short rsvd; + /* seqptr's */ +}; + +/* + * An announcement packet. + */ +struct pkt_id { + u_int32_t pi_mslot; + struct PageID pi_mpage; /* current page */ + struct pgstate pi_ps; + /* seqptr's */ + /* null-terminated site name */ +}; + +struct pkt_preq { + struct PageID pp_page; + u_int32_t pp_low; + u_int32_t pp_high; +}; + +struct pkt_prep { + u_int32_t pp_n; /* size of pageid array */ + /* pgstate's follow */ +}; + +static int +wb_id(const struct pkt_id *id, u_int len) +{ + int i; + const char *cp; + const struct id_off *io; + char c; + int nid; + + printf(" wb-id:"); + len -= sizeof(*id); + if (len < 0 || (u_char *)(id + 1) > snapend) + return (-1); + + printf(" %u/%s:%u (max %u/%s:%u) ", + (u_int32_t)ntohl(id->pi_ps.slot), + ipaddr_string(&id->pi_ps.page.p_sid), + (u_int32_t)ntohl(id->pi_ps.page.p_uid), + (u_int32_t)ntohl(id->pi_mslot), + ipaddr_string(&id->pi_mpage.p_sid), + (u_int32_t)ntohl(id->pi_mpage.p_uid)); + + nid = ntohs(id->pi_ps.nid); + len -= sizeof(*io) * nid; + io = (struct id_off *)(id + 1); + cp = (char *)(io + nid); + if ((u_char *)cp + len <= snapend) { + putchar('"'); + (void)fn_print((u_char *)cp, (u_char *)cp + len); + putchar('"'); + } + + c = '<'; + for (i = 0; i < nid && (u_char *)io < snapend; ++io, ++i) { + printf("%c%s:%u", + c, ipaddr_string(&io->id), (u_int32_t)ntohl(io->off)); + c = ','; + } + if (i >= nid) { + printf(">"); + return (0); + } + return (-1); +} + +static int +wb_rreq(const struct pkt_rreq *rreq, u_int len) +{ + printf(" wb-rreq:"); + if (len < sizeof(*rreq) || (u_char *)(rreq + 1) > snapend) + return (-1); + + printf(" please repair %s %s:%u<%u:%u>", + ipaddr_string(&rreq->pr_id), + ipaddr_string(&rreq->pr_page.p_sid), + (u_int32_t)ntohl(rreq->pr_page.p_uid), + (u_int32_t)ntohl(rreq->pr_sseq), + (u_int32_t)ntohl(rreq->pr_eseq)); + return (0); +} + +static int +wb_preq(const struct pkt_preq *preq, u_int len) +{ + printf(" wb-preq:"); + if (len < sizeof(*preq) || (u_char *)(preq + 1) > snapend) + return (-1); + + printf(" need %u/%s:%u", + (u_int32_t)ntohl(preq->pp_low), + ipaddr_string(&preq->pp_page.p_sid), + (u_int32_t)ntohl(preq->pp_page.p_uid)); + return (0); +} + +static int +wb_prep(const struct pkt_prep *prep, u_int len) +{ + int n; + const struct pgstate *ps; + const u_char *ep = snapend; + + printf(" wb-prep:"); + if (len < sizeof(*prep)) { + return (-1); + } + n = ntohl(prep->pp_n); + ps = (const struct pgstate *)(prep + 1); + while (--n >= 0 && (u_char *)ps < ep) { + const struct id_off *io, *ie; + char c = '<'; + + printf(" %u/%s:%u", + (u_int32_t)ntohl(ps->slot), + ipaddr_string(&ps->page.p_sid), + (u_int32_t)ntohl(ps->page.p_uid)); + io = (struct id_off *)(ps + 1); + for (ie = io + ps->nid; io < ie && (u_char *)io < ep; ++io) { + printf("%c%s:%u", c, ipaddr_string(&io->id), + (u_int32_t)ntohl(io->off)); + c = ','; + } + printf(">"); + ps = (struct pgstate *)io; + } + return ((u_char *)ps <= ep? 0 : -1); +} + + +char *dopstr[] = { + "dop-0!", + "dop-1!", + "RECT", + "LINE", + "ML", + "DEL", + "XFORM", + "ELL", + "CHAR", + "STR", + "NOP", + "PSCODE", + "PSCOMP", + "REF", + "SKIP", + "HOLE", +}; + +static int +wb_dops(const struct dophdr *dh, u_int32_t ss, u_int32_t es) +{ + printf(" <"); + for ( ; ss <= es; ++ss) { + register int t = dh->dh_type; + + if (t > DT_MAXTYPE) + printf(" dop-%d!", t); + else { + printf(" %s", dopstr[t]); + if (t == DT_SKIP || t == DT_HOLE) { + int ts = ntohl(dh->dh_ts); + printf("%d", ts - ss + 1); + if (ss > ts || ts > es) { + printf("[|]"); + if (ts < ss) + return (0); + } + ss = ts; + } + } + dh = DOP_NEXT(dh); + if ((u_char *)dh > snapend) { + printf("[|wb]"); + break; + } + } + printf(" >"); + return (0); +} + +static int +wb_rrep(const struct pkt_rrep *rrep, u_int len) +{ + const struct pkt_dop *dop = &rrep->pr_dop; + + printf(" wb-rrep:"); + len -= sizeof(*rrep); + if (len < 0 || (u_char *)(rrep + 1) > snapend) + return (-1); + + printf(" for %s %s:%u<%u:%u>", + ipaddr_string(&rrep->pr_id), + ipaddr_string(&dop->pd_page.p_sid), + (u_int32_t)ntohl(dop->pd_page.p_uid), + (u_int32_t)ntohl(dop->pd_sseq), + (u_int32_t)ntohl(dop->pd_eseq)); + + if (vflag) + return (wb_dops((const struct dophdr *)(dop + 1), + ntohl(dop->pd_sseq), ntohl(dop->pd_eseq))); + return (0); +} + +static int +wb_drawop(const struct pkt_dop *dop, u_int len) +{ + printf(" wb-dop:"); + len -= sizeof(*dop); + if (len < 0 || (u_char *)(dop + 1) > snapend) + return (-1); + + printf(" %s:%u<%u:%u>", + ipaddr_string(&dop->pd_page.p_sid), + (u_int32_t)ntohl(dop->pd_page.p_uid), + (u_int32_t)ntohl(dop->pd_sseq), + (u_int32_t)ntohl(dop->pd_eseq)); + + if (vflag) + return (wb_dops((const struct dophdr *)(dop + 1), + ntohl(dop->pd_sseq), ntohl(dop->pd_eseq))); + return (0); +} + +/* + * Print whiteboard multicast packets. + */ +void +wb_print(register const void *hdr, register u_int len) +{ + register const struct pkt_hdr *ph; + + ph = (const struct pkt_hdr *)hdr; + len -= sizeof(*ph); + if (len < 0 || (u_char *)(ph + 1) <= snapend) { + if (ph->ph_flags) + printf("*"); + switch (ph->ph_type) { + + case PT_KILL: + printf(" wb-kill"); + return; + + case PT_ID: + if (wb_id((struct pkt_id *)(ph + 1), len) >= 0) + return; + break; + + case PT_RREQ: + if (wb_rreq((struct pkt_rreq *)(ph + 1), len) >= 0) + return; + break; + + case PT_RREP: + if (wb_rrep((struct pkt_rrep *)(ph + 1), len) >= 0) + return; + break; + + case PT_DRAWOP: + if (wb_drawop((struct pkt_dop *)(ph + 1), len) >= 0) + return; + break; + + case PT_PREQ: + if (wb_preq((struct pkt_preq *)(ph + 1), len) >= 0) + return; + break; + + case PT_PREP: + if (wb_prep((struct pkt_prep *)(ph + 1), len) >= 0) + return; + break; + + default: + printf(" wb-%d!", ph->ph_type); + return; + } + } + printf("[|wb]"); +} diff --git a/tcpdump.tproj/strcasecmp.c b/tcpdump.tproj/strcasecmp.c new file mode 100644 index 0000000..edb886a --- /dev/null +++ b/tcpdump.tproj/strcasecmp.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1987 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that this notice is preserved and that due credit is given + * to the University of California at Berkeley. The name of the University + * may not be used to endorse or promote products derived from this + * software without specific written prior permission. This software + * is provided ``as is'' without express or implied warranty. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static const char sccsid[] = "@(#)strcasecmp.c 5.5 (Berkeley) 11/24/87"; +#endif /* LIBC_SCCS and not lint */ + +#include + +#include "interface.h" + +/* + * This array is designed for mapping upper and lower case letter + * together for a case independent comparison. The mappings are + * based upon ascii character sequences. + */ +static u_char charmap[] = { + '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', + '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', + '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', + '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', + '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', + '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', + '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', + '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', + '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', + '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', + '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', + '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', + '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', + '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', + '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', + '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', + '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', + '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', + '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', + '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', + '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', + '\300', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\333', '\334', '\335', '\336', '\337', + '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', + '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', + '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', + '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', +}; + +__private_extern__ +int +strcasecmp(s1, s2) + const char *s1, *s2; +{ + register u_char *cm = charmap, + *us1 = (u_char *)s1, + *us2 = (u_char *)s2; + + while (cm[*us1] == cm[*us2++]) + if (*us1++ == '\0') + return(0); + return(cm[*us1] - cm[*--us2]); +} + +int +strncasecmp(s1, s2, n) + const char *s1, *s2; + register int n; +{ + register u_char *cm = charmap, + *us1 = (u_char *)s1, + *us2 = (u_char *)s2; + + while (--n >= 0 && cm[*us1] == cm[*us2++]) + if (*us1++ == '\0') + return(0); + return(n < 0 ? 0 : cm[*us1] - cm[*--us2]); +} diff --git a/tcpdump.tproj/tcpdump.c b/tcpdump.tproj/tcpdump.c new file mode 100644 index 0000000..5ad2561 --- /dev/null +++ b/tcpdump.tproj/tcpdump.c @@ -0,0 +1,451 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char copyright[] = + "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996\n\ +The Regents of the University of California. All rights reserved.\n"; +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/tcpdump.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)"; +#endif + +/* + * tcpdump - monitor tcp/ip traffic on an ethernet. + * + * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. + * Mercilessly hacked and occasionally improved since then via the + * combined efforts of Van, Steve McCanne and Craig Leres of LBL. + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "interface.h" +#include "addrtoname.h" +#include "machdep.h" + +int fflag; /* don't translate "foreign" IP address */ +int nflag; /* leave addresses as numbers */ +int Nflag; /* remove domains from printed host names */ +int pflag; /* don't go promiscuous */ +int qflag; /* quick (shorter) output */ +int tflag = 1; /* print packet arrival time */ +int eflag; /* print ethernet header */ +int vflag; /* verbose */ +int xflag; /* print packet in hex */ +int Oflag = 1; /* run filter code optimizer */ +int Sflag; /* print raw TCP sequence numbers */ +int packettype; + +int dflag; /* print filter code */ + +char *program_name; + +int32_t thiszone; /* seconds offset from gmt to local time */ + +/* Externs */ +extern void bpf_dump(struct bpf_program *, int); + +/* Forwards */ +RETSIGTYPE cleanup(int); +extern __dead void usage(void) __attribute__((volatile)); + +/* Length of saved portion of packet. */ +int snaplen = DEFAULT_SNAPLEN; + +struct printer { + pcap_handler f; + int type; +}; + +/* XXX needed if using old bpf.h */ +#ifndef DLT_ATM_RFC1483 +#define DLT_ATM_RFC1483 11 +#endif + +static struct printer printers[] = { + { ether_if_print, DLT_EN10MB }, + { ether_if_print, DLT_IEEE802 }, + { sl_if_print, DLT_SLIP }, + { ppp_if_print, DLT_PPP }, + { fddi_if_print, DLT_FDDI }, + { null_if_print, DLT_NULL }, + { atm_if_print, DLT_ATM_RFC1483 }, + { NULL, 0 }, +}; + +static pcap_handler +lookup_printer(int type) +{ + struct printer *p; + + for (p = printers; p->f; ++p) + if (type == p->type) + return p->f; + + error("unknown data link type 0x%x", type); + /* NOTREACHED */ +} + +static pcap_t *pd; + +extern int optind; +extern int opterr; +extern char *optarg; + +int +main(int argc, char **argv) +{ + register int cnt, op, i; + bpf_u_int32 localnet, netmask; + register char *cp, *infile, *cmdbuf, *device, *RFileName, *WFileName; + pcap_handler printer; + struct bpf_program fcode; + u_char *pcap_userdata; + char ebuf[PCAP_ERRBUF_SIZE]; + + cnt = -1; + device = NULL; + infile = NULL; + RFileName = NULL; + WFileName = NULL; + if ((cp = strrchr(argv[0], '/')) != NULL) + program_name = cp + 1; + else + program_name = argv[0]; + + if (abort_on_misalignment(ebuf) < 0) + error("%s", ebuf); + + opterr = 0; + while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:StT:vw:xY")) != -1) + switch (op) { + case 'c': + cnt = atoi(optarg); + if (cnt <= 0) + error("invalid packet count %s", optarg); + break; + + case 'd': + ++dflag; + break; + + case 'e': + ++eflag; + break; + + case 'f': + ++fflag; + break; + + case 'F': + infile = optarg; + break; + + case 'i': + device = optarg; + break; + + case 'l': +#ifdef HAVE_SETLINEBUF + setlinebuf(stdout); +#else + setvbuf(stdout, NULL, _IOLBF, 0); +#endif + break; + + case 'n': + ++nflag; + break; + + case 'N': + ++Nflag; + break; + + case 'O': + Oflag = 0; + break; + + case 'p': + ++pflag; + break; + + case 'q': + ++qflag; + break; + + case 'r': + RFileName = optarg; + break; + + case 's': + snaplen = atoi(optarg); + if (snaplen <= 0) + error("invalid snaplen %s", optarg); + break; + + case 'S': + ++Sflag; + break; + + case 't': + --tflag; + break; + + case 'T': + if (strcasecmp(optarg, "vat") == 0) + packettype = PT_VAT; + else if (strcasecmp(optarg, "wb") == 0) + packettype = PT_WB; + else if (strcasecmp(optarg, "rpc") == 0) + packettype = PT_RPC; + else if (strcasecmp(optarg, "rtp") == 0) + packettype = PT_RTP; + else if (strcasecmp(optarg, "rtcp") == 0) + packettype = PT_RTCP; + else + error("unknown packet type `%s'", optarg); + break; + + case 'v': + ++vflag; + break; + + case 'w': + WFileName = optarg; + break; +#ifdef YYDEBUG + case 'Y': + { + /* Undocumented flag */ + extern int yydebug; + yydebug = 1; + } + break; +#endif + case 'x': + ++xflag; + break; + + default: + usage(); + /* NOTREACHED */ + } + + if (tflag > 0) + thiszone = gmt2local(); + + if (RFileName != NULL) { + /* + * We don't need network access, so set it back to the user id. + * Also, this prevents the user from reading anyone's + * trace file. + */ + setuid(getuid()); + + pd = pcap_open_offline(RFileName, ebuf); + if (pd == NULL) + error("%s", ebuf); + localnet = 0; + netmask = 0; + if (fflag != 0) + error("-f and -r options are incompatible"); + } else { + if (device == NULL) { + device = pcap_lookupdev(ebuf); + if (device == NULL) + error("%s", ebuf); + } + pd = pcap_open_live(device, snaplen, !pflag, 1000, ebuf); + if (pd == NULL) + error("%s", ebuf); + i = pcap_snapshot(pd); + if (snaplen < i) { + warning("snaplen raised from %d to %d", snaplen, i); + snaplen = i; + } + if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) + error("%s", ebuf); + /* + * Let user own process after socket has been opened. + */ + setuid(getuid()); + } + if (infile) + cmdbuf = read_infile(infile); + else + cmdbuf = copy_argv(&argv[optind]); + + if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) + error("%s", pcap_geterr(pd)); + if (dflag) { + bpf_dump(&fcode, dflag); + exit(0); + } + init_addrtoname(fflag, localnet, netmask); + + (void)signal(SIGTERM, cleanup); + (void)signal(SIGINT, cleanup); + (void)signal(SIGHUP, cleanup); + + if (pcap_setfilter(pd, &fcode) < 0) + error("%s", pcap_geterr(pd)); + if (WFileName) { + pcap_dumper_t *p = pcap_dump_open(pd, WFileName); + if (p == NULL) + error("%s", pcap_geterr(pd)); + printer = pcap_dump; + pcap_userdata = (u_char *)p; + } else { + printer = lookup_printer(pcap_datalink(pd)); + pcap_userdata = 0; + } + if (RFileName == NULL) { + (void)fprintf(stderr, "%s: listening on %s\n", + program_name, device); + (void)fflush(stderr); + } + if (pcap_loop(pd, cnt, printer, pcap_userdata) < 0) { + (void)fprintf(stderr, "%s: pcap_loop: %s\n", + program_name, pcap_geterr(pd)); + exit(1); + } + pcap_close(pd); + exit(0); +} + +/* make a clean exit on interrupts */ +RETSIGTYPE +cleanup(int signo) +{ + struct pcap_stat stat; + + /* Can't print the summary if reading from a savefile */ + if (pd != NULL && pcap_file(pd) == NULL) { + (void)fflush(stdout); + putc('\n', stderr); + if (pcap_stats(pd, &stat) < 0) + (void)fprintf(stderr, "pcap_stats: %s\n", + pcap_geterr(pd)); + else { + (void)fprintf(stderr, "%d packets received by filter\n", + stat.ps_recv); + (void)fprintf(stderr, "%d packets dropped by kernel\n", + stat.ps_drop); + } + } + exit(0); +} + +/* Like default_print() but data need not be aligned */ +void +default_print_unaligned(register const u_char *cp, register u_int length) +{ + register u_int i, s; + register int nshorts; + + nshorts = (u_int) length / sizeof(u_short); + i = 0; + while (--nshorts >= 0) { + if ((i++ % 8) == 0) + (void)printf("\n\t\t\t"); + s = *cp++; + (void)printf(" %02x%02x", s, *cp++); + } + if (length & 1) { + if ((i % 8) == 0) + (void)printf("\n\t\t\t"); + (void)printf(" %02x", *cp); + } +} + +void +default_print(register const u_char *bp, register u_int length) +{ + register const u_short *sp; + register u_int i; + register int nshorts; + + if ((long)bp & 1) { + default_print_unaligned(bp, length); + return; + } + sp = (u_short *)bp; + nshorts = (u_int) length / sizeof(u_short); + i = 0; + while (--nshorts >= 0) { + if ((i++ % 8) == 0) + (void)printf("\n\t\t\t"); + (void)printf(" %04x", ntohs(*sp++)); + } + if (length & 1) { + if ((i % 8) == 0) + (void)printf("\n\t\t\t"); + (void)printf(" %02x", *(u_char *)sp); + } +} + +__dead void +usage(void) +{ + extern char version[]; + + (void)fprintf(stderr, "Version %s\n", version); + (void)fprintf(stderr, +"Usage: tcpdump [-deflnNOpqStvx] [-c count] [ -F file ]\n"); + (void)fprintf(stderr, +"\t\t[ -i interface ] [ -r file ] [ -s snaplen ]\n"); + (void)fprintf(stderr, +"\t\t[ -T type ] [ -w file ] [ expression ]\n"); + exit(-1); +} diff --git a/tcpdump.tproj/util.c b/tcpdump.tproj/util.c new file mode 100644 index 0000000..6df0352 --- /dev/null +++ b/tcpdump.tproj/util.c @@ -0,0 +1,352 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/util.c,v 1.1.1.1 1999/05/02 03:58:34 wsanchez Exp $ (LBL)"; +#endif + +#include +#include +#include +#include + +#include +#include +#ifdef HAVE_FCNTL_H +#include +#endif +#include +#include +#if __STDC__ +#include +#else +#include +#endif +#include +#include +#ifdef TIME_WITH_SYS_TIME +#include +#endif +#include + +#include "interface.h" + +/* + * Print out a filename (or other ascii string). + * If ep is NULL, assume no truncation check is needed. + * Return true if truncated. + */ +int +fn_print(register const u_char *s, register const u_char *ep) +{ + register int ret; + register u_char c; + + ret = 1; /* assume truncated */ + while (ep == NULL || s < ep) { + c = *s++; + if (c == '\0') { + ret = 0; + break; + } + if (!isascii(c)) { + c = toascii(c); + putchar('M'); + putchar('-'); + } + if (!isprint(c)) { + c ^= 0x40; /* DEL to ?, others to alpha */ + putchar('^'); + } + putchar(c); + } + return(ret); +} + +/* + * Print out a counted filename (or other ascii string). + * If ep is NULL, assume no truncation check is needed. + * Return true if truncated. + */ +int +fn_printn(register const u_char *s, register u_int n, + register const u_char *ep) +{ + register int ret; + register u_char c; + + ret = 1; /* assume truncated */ + while (ep == NULL || s < ep) { + if (n-- <= 0) { + ret = 0; + break; + } + c = *s++; + if (!isascii(c)) { + c = toascii(c); + putchar('M'); + putchar('-'); + } + if (!isprint(c)) { + c ^= 0x40; /* DEL to ?, others to alpha */ + putchar('^'); + } + putchar(c); + } + return(ret); +} + +/* + * Print the timestamp + */ +void +ts_print(register const struct timeval *tvp) +{ + register int s; + + if (tflag > 0) { + /* Default */ + s = (tvp->tv_sec + thiszone) % 86400; + (void)printf("%02d:%02d:%02d.%06u ", + s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec); + } else if (tflag < 0) { + /* Unix timeval style */ + (void)printf("%u.%06u ", + (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec); + } +} + +/* + * Convert a token value to a string; use "fmt" if not found. + */ +const char * +tok2str(register const struct tok *lp, register const char *fmt, + register int v) +{ + static char buf[128]; + + while (lp->s != NULL) { + if (lp->v == v) + return (lp->s); + ++lp; + } + if (fmt == NULL) + fmt = "#%d"; + (void)sprintf(buf, fmt, v); + return (buf); +} + + +/* VARARGS */ +__dead void +#if __STDC__ +error(const char *fmt, ...) +#else +error(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; + + (void)fprintf(stderr, "%s: ", program_name); +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + if (*fmt) { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); + } + exit(1); + /* NOTREACHED */ +} + +/* VARARGS */ +void +#if __STDC__ +warning(const char *fmt, ...) +#else +warning(fmt, va_alist) + const char *fmt; + va_dcl +#endif +{ + va_list ap; + + (void)fprintf(stderr, "%s: WARNING: ", program_name); +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + if (*fmt) { + fmt += strlen(fmt); + if (fmt[-1] != '\n') + (void)fputc('\n', stderr); + } +} + +/* + * Copy arg vector into a new buffer, concatenating arguments with spaces. + */ +char * +copy_argv(register char **argv) +{ + register char **p; + register u_int len = 0; + char *buf; + char *src, *dst; + + p = argv; + if (*p == 0) + return 0; + + while (*p) + len += strlen(*p++) + 1; + + buf = (char *)malloc(len); + if (buf == NULL) + error("copy_argv: malloc"); + + p = argv; + dst = buf; + while ((src = *p++) != NULL) { + while ((*dst++ = *src++) != '\0') + ; + dst[-1] = ' '; + } + dst[-1] = '\0'; + + return buf; +} + +/* A replacement for strdup() that cuts down on malloc() overhead */ +char * +savestr(register const char *str) +{ + register u_int size; + register char *p; + static char *strptr = NULL; + static u_int strsize = 0; + + size = strlen(str) + 1; + if (size > strsize) { + strsize = 1024; + if (strsize < size) + strsize = size; + strptr = (char *)malloc(strsize); + if (strptr == NULL) + error("savestr: malloc"); + } + (void)strcpy(strptr, str); + p = strptr; + strptr += size; + strsize -= size; + return (p); +} + +char * +read_infile(char *fname) +{ + register int fd, cc; + register char *cp; + struct stat buf; + + fd = open(fname, O_RDONLY); + if (fd < 0) + error("can't open %s: %s", fname, pcap_strerror(errno)); + + if (fstat(fd, &buf) < 0) + error("can't stat %s: %s", fname, pcap_strerror(errno)); + + cp = malloc((u_int)buf.st_size + 1); + cc = read(fd, cp, (int)buf.st_size); + if (cc < 0) + error("read %s: %s", fname, pcap_strerror(errno)); + if (cc != buf.st_size) + error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); + cp[(int)buf.st_size] = '\0'; + + return (cp); +} + +/* + * Returns the difference between gmt and local time in seconds. + * Use gmtime() and localtime() to keep things simple. + */ +int32_t +gmt2local(void) +{ + register int dt, dir; + register struct tm *gmt, *loc; + time_t t; + struct tm sgmt; + + t = time(NULL); + gmt = &sgmt; + *gmt = *gmtime(&t); + loc = localtime(&t); + dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 + + (loc->tm_min - gmt->tm_min) * 60; + + /* + * If the year or julian day is different, we span 00:00 GMT + * and must add or subtract a day. Check the year first to + * avoid problems when the julian day wraps. + */ + dir = loc->tm_year - gmt->tm_year; + if (dir == 0) + dir = loc->tm_yday - gmt->tm_yday; + dt += dir * 24 * 60 * 60; + + return (dt); +} diff --git a/tcpdump.tproj/version.c b/tcpdump.tproj/version.c new file mode 100644 index 0000000..2ee34ff --- /dev/null +++ b/tcpdump.tproj/version.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: version.c,v 1.4 1996/07/13 11:01:35 mickey Exp $ */ +/* $NetBSD: version.c,v 1.3 1996/05/20 00:41:20 fvdl Exp $ */ + +char version[] = "3.2.0"; diff --git a/tcpdump.tproj/vfprintf.c b/tcpdump.tproj/vfprintf.c new file mode 100644 index 0000000..3d5e80c --- /dev/null +++ b/tcpdump.tproj/vfprintf.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that: (1) source code distributions + * retain the above copyright notice and this paragraph in its entirety, (2) + * distributions including binary code include the above copyright notice and + * this paragraph in its entirety in the documentation or other materials + * provided with the distribution, and (3) all advertising materials mentioning + * features or use of this software display the following acknowledgement: + * ``This product includes software developed by the University of California, + * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of + * the University nor the names of its contributors may be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /cvs/Darwin/Commands/NeXT/network_cmds/tcpdump.tproj/vfprintf.c,v 1.1.1.1 1999/05/02 03:58:35 wsanchez Exp $ (LBL)"; +#endif + +#include + +#include +#if __STDC__ +#include +#else +#include +#endif +#include +#include + +#include "interface.h" + +#if 0 + +/* + * Stock 4.3 doesn't have vfprintf. + * This routine is due to Chris Torek. + */ +vfprintf(f, fmt, args) + FILE *f; + char *fmt; + va_list args; +{ + int ret; + + if ((f->_flag & _IOWRT) == 0) { + if (f->_flag & _IORW) + f->_flag |= _IOWRT; + else + return EOF; + } + ret = _doprnt(fmt, args, f); + return ferror(f) ? EOF : ret; +} +#endif /* 0 */ \ No newline at end of file diff --git a/telnet.tproj/Makefile b/telnet.tproj/Makefile new file mode 100644 index 0000000..0a096f6 --- /dev/null +++ b/telnet.tproj/Makefile @@ -0,0 +1,57 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = telnet + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = externs.h fdset.h general.h krb4-proto.h ring.h types.h\ + defines.h + +CFILES = authenc.c commands.c main.c network.c ring.c sys_bsd.c\ + telnet.c terminal.c tn3270.c utilities.c + +OTHERSRCS = Makefile.preamble Makefile README telnet.1 Makefile.dist + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4 +WINDOWS_PB_CFLAGS = -DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4 +PDO_UNIX_PB_CFLAGS = -DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4 + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/telnet.tproj/Makefile.dist b/telnet.tproj/Makefile.dist new file mode 100644 index 0000000..2e38a28 --- /dev/null +++ b/telnet.tproj/Makefile.dist @@ -0,0 +1,73 @@ +# +# Copyright (c) 1990 The Regents of the University of California. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)Makefile 8.1 (Berkeley) 6/6/93 +# + +PROG= telnet + +CFLAGS+=-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DAUTHENTICATION -DENCRYPTION +CFLAGS+=-DENV_HACK +CFLAGS+=-I${.CURDIR}/../../lib + +CFLAGS+= -DKRB4 + +LDADD= -ltermcap -ltelnet +LDADD+= -lkrb -ldes +DPADD= ${LIBTERMCAP} + +SRCS= authenc.c commands.c main.c network.c ring.c sys_bsd.c telnet.c \ + terminal.c tn3270.c utilities.c + +# These are the sources that have encryption stuff in them. +CRYPT_SRC= authenc.c commands.c externs.h main.c network.c +CRYPT_SRC+= ring.c ring.h telnet.c terminal.c utilities.c Makefile +NOCRYPT_DIR=${.CURDIR}/Nocrypt + +.include + +nocrypt: +#ifdef ENCRYPTION + @for i in ${CRYPT_SRC}; do \ + if [ ! -d ${NOCRYPT_DIR} ]; then \ + echo Creating subdirectory ${NOCRYPT_DIR}; \ + mkdir ${NOCRYPT_DIR}; \ + fi; \ + echo ${NOCRYPT_DIR}/$$i; \ + unifdef -UENCRYPTION ${.CURDIR}/$$i | \ + sed "s/ || defined(ENCRYPTION)//" > ${NOCRYPT_DIR}/$$i; \ + done + +placeholder: +#else /* ENCRYPTION */ + @echo "Encryption code already removed." +#endif /* ENCRYPTION */ diff --git a/telnet.tproj/Makefile.preamble b/telnet.tproj/Makefile.preamble new file mode 100644 index 0000000..0f58055 --- /dev/null +++ b/telnet.tproj/Makefile.preamble @@ -0,0 +1,4 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_GENERATED_OFILES = $(VERS_OFILE) +OTHER_LIBS = -ltelnet +-include ../Makefile.include diff --git a/telnet.tproj/PB.project b/telnet.tproj/PB.project new file mode 100644 index 0000000..23bd9c5 --- /dev/null +++ b/telnet.tproj/PB.project @@ -0,0 +1,47 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (externs.h, fdset.h, general.h, "krb4-proto.h", ring.h, types.h, defines.h); + OTHER_LIBS = (); + OTHER_LINKED = ( + authenc.c, + commands.c, + main.c, + network.c, + ring.c, + sys_bsd.c, + telnet.c, + terminal.c, + tn3270.c, + utilities.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, README, telnet.1, Makefile.dist); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4"; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = "-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4"; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = telnet; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = "-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK # -DAUTHENTICATION -DENCRYPTION -DKRB4"; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/telnet.tproj/README b/telnet.tproj/README new file mode 100644 index 0000000..37b588f --- /dev/null +++ b/telnet.tproj/README @@ -0,0 +1,743 @@ + +This is a distribution of both client and server telnet. These programs +have been compiled on: + telnet telnetd + 4.4 BSD-Lite x x + 4.3 BSD Reno X X + UNICOS 9.1 X X + UNICOS 9.0 X X + UNICOS 8.0 X X + BSDI 2.0 X X + Solaris 2.4 x x (no linemode in server) + SunOs 4.1.4 X X (no linemode in server) + Ultrix 4.3 X X (no linemode in server) + Ultrix 4.1 X X (no linemode in server) + +In addition, previous versions have been compiled on the following +machines, but were not available for testing this version. + telnet telnetd + Next1.0 X X + UNICOS 8.3 X X + UNICOS 7.C X X + UNICOS 7.0 X X + SunOs 4.0.3c X X (no linemode in server) + 4.3 BSD X X (no linemode in server) + DYNIX V3.0.12 X X (no linemode in server) + Ultrix 3.1 X X (no linemode in server) + Ultrix 4.0 X X (no linemode in server) + SunOs 3.5 X X (no linemode in server) + SunOs 4.1.3 X X (no linemode in server) + Solaris 2.2 x x (no linemode in server) + Solaris 2.3 x x (no linemode in server) + BSDI 1.0 X X + BSDI 1.1 X X + DYNIX V3.0.17.9 X X (no linemode in server) + HP-UX 8.0 x x (no linemode in server) + +This code should work, but there are no guarantees. + +May 30, 1995 + +This release represents what is on the 4.4BSD-Lite2 release, which +should be the final BSD release. I will continue to support of +telnet, The code (without encryption) is available via anonymous ftp +from ftp.cray.com, in src/telnet/telnet.YY.MM.DD.NE.tar.Z, where +YY.MM.DD is replaced with the year, month and day of the release. +If you can't find it at one of these places, at some point in the +near future information about the latest releases should be available +from ftp.borman.com. + +In addition, the version with the encryption code is available via +ftp from net-dist.mit.edu, in the directory /pub/telnet. There +is a README file there that gives further information on how +to get the distribution. + +Questions, comments, bug reports and bug fixes can be sent to +one of these addresses: + dab@borman.com + dab@cray.com + dab@bsdi.com + +This release is mainly bug fixes and code cleanup. + + Replace all calls to bcopy()/bzero() with calls to + memmove()/memset() and all calls to index()/rindex() + with calls to strchr()/strrchr(). + + Add some missing diagnostics for option tracing + to telnetd. + + Add support for BSDI 2.0 and Solaris 2.4. + + Add support for UNICOS 8.0 + + Get rid of expanded tabs and trailing white spaces. + + From Paul Vixie: + Fix for telnet going into an endless spin + when the session dies abnormally. + + From Jef Poskanzer: + Changes to allow telnet to compile + under SunOS 3.5. + + From Philip Guenther: + makeutx() doesn't expand utmpx, + use pututxline() instead. + + From Chris Torek: + Add a sleep(1) before execing login + to avoid race condition that can eat + up the login prompt. + Use terminal speed directly if it is + not an encoded value. + + From Steve Parker: + Fix to realloc() call. Fix for execing + login on solaris with no user name. + +January 19, 1994 + +This is a list of some of the changes since the last tar release +of telnet/telnetd. There are probably other changes that aren't +listed here, but this should hit a lot of the main ones. + + General: + Changed #define for AUTHENTICATE to AUTHENTICATION + Changed #define for ENCRYPT to ENCRYPTION + Changed #define for DES_ENCRYPT to DES_ENCRYPTION + + Added support for SPX authentication: -DSPX + + Added support for Kerberos Version 5 authentication: -DKRB5 + + Added support for ANSI C function prototypes + + Added support for the NEW-ENVIRON option (RFC-1572) + including support for USERVAR. + + Made support for the old Environment Option (RFC-1408) + conditional on -DOLD_ENVIRON + + Added #define ENV_HACK - support for RFC 1571 + + The encryption code is removed from the public distributions. + Domestic 4.4 BSD distributions contain the encryption code. + + ENV_HACK: Code to deal with systems that only implement + the old ENVIRON option, and have reversed definitions + of ENV_VAR and ENV_VAL. Also fixes ENV processing in + client to handle things besides just the default set... + + NO_BSD_SETJMP: UNICOS configuration for + UNICOS 6.1/6.0/5.1/5.0 systems. + + STREAMSPTY: Use /dev/ptmx to get a clean pty. This + is for SVr4 derivatives (Like Solaris) + + UTMPX: For systems that have /etc/utmpx. This is for + SVr4 derivatives (Like Solaris) + + Definitions for BSDI 1.0 + + Definitions for 4.3 Reno and 4.4 BSD. + + Definitions for UNICOS 8.0 and UNICOS 7.C + + Definitions for Solaris 2.0 + + Definitions for HP-UX 8.0 + + Latest Copyright notices from Berkeley. + + FLOW-CONTROL: support for RFC-XXXx + + + Client Specific: + + Fix the "send" command to not send garbage... + + Fix status message for "skiprc" + + Make sure to send NAWS after telnet has been suspended + or an external command has been run, if the window size + has changed. + + sysV88 support. + + Server Specific: + + Support flowcontrol option in non-linemode servers. + + -k Server supports Kludge Linemode, but will default to + either single character mode or real Linemode support. + The user will have to explicitly ask to switch into + kludge linemode. ("stty extproc", or escape back to + to telnet and say "mode line".) + + -u Specify the length of the hostname field in the utmp + file. Hostname longer than this length will be put + into the utmp file in dotted decimal notation, rather + than putting in a truncated hostname. + + -U Registered hosts only. If a reverse hostname lookup + fails, the connection will be refused. + + -f/-F + Allows forwarding of credentials for KRB5. + +Februrary 22, 1991: + + Features: + + This version of telnet/telnetd has support for both + the AUTHENTICATION and ENCRYPTION options. The + AUTHENTICATION option is fairly well defined, and + an option number has been assigned to it. The + ENCRYPTION option is still in a state of flux; an + option number has been assigned to, but it is still + subject to change. The code is provided in this release + for experimental and testing purposes. + + The telnet "send" command can now be used to send + do/dont/will/wont commands, with any telnet option + name. The rules for when do/dont/will/wont are sent + are still followed, so just because the user requests + that one of these be sent doesn't mean that it will + be sent... + + The telnet "getstatus" command no longer requires + that option printing be enabled to see the response + to the "DO STATUS" command. + + A -n flag has been added to telnetd to disable + keepalives. + + A new telnet command, "auth" has been added (if + AUTHENTICATE is defined). It has four sub-commands, + "status", "disable", "enable" and "help". + + A new telnet command, "encrypt" has been added (if + ENCRYPT is defined). It has many sub-commands: + "enable", "type", "start", "stop", "input", + "-input", "output", "-output", "status", and "help". + + The LOGOUT option is now supported by both telnet + and telnetd, a new command, "logout", was added + to support this. + + Several new toggle options were added: + "autoencrypt", "autodecrypt", "autologin", "authdebug", + "encdebug", "skiprc", "verbose_encrypt" + + An "rlogin" interface has been added. If the program + is named "rlogin", or the "-r" flag is given, then + an rlogin type of interface will be used. + ~. Terminates the session + ~ Suspend the session + ~^] Escape to telnet command mode + ~~ Pass through the ~. + BUG: If you type the rlogin escape character + in the middle of a line while in rlogin + mode, you cannot erase it or any characters + before it. Hopefully this can be fixed + in a future release... + + General changes: + + A "libtelnet.a" has now been created. This libraray + contains code that is common to both telnet and + telnetd. This is also where library routines that + are needed, but are not in the standard C library, + are placed. + + The makefiles have been re-done. All of the site + specific configuration information has now been put + into a single "Config.generic" file, in the top level + directory. Changing this one file will take care of + all three subdirectories. Also, to add a new/local + definition, a "Config.local" file may be created + at the top level; if that file exists, the subdirectories + will use that file instead of "Config.generic". + + Many 1-2 line functions in commands.c have been + removed, and just inserted in-line, or replaced + with a macro. + + Bug Fixes: + + The non-termio code in both telnet and telnetd was + setting/clearing CTLECH in the sg_flags word. This + was incorrect, and has been changed to set/clear the + LCTLECH bit in the local mode word. + + The SRCRT #define has been removed. If IP_OPTIONS + and IPPROTO_IP are defined on the system, then the + source route code is automatically enabled. + + The NO_GETTYTAB #define has been removed; there + is a compatability routine that can be built into + libtelnet to achive the same results. + + The server, telnetd, has been switched to use getopt() + for parsing the argument list. + + The code for getting the input/output speeds via + cfgetispeed()/cfgetospeed() was still not quite + right in telnet. Posix says if the ispeed is 0, + then it is really equal to the ospeed. + + The suboption processing code in telnet now has + explicit checks to make sure that we received + the entire suboption (telnetd was already doing this). + + The telnet code for processing the terminal type + could cause a core dump if an existing connection + was closed, and a new connection opened without + exiting telnet. + + Telnetd was doing a TCSADRAIN when setting the new + terminal settings; This is not good, because it means + that the tcsetattr() will hang waiting for output to + drain, and telnetd is the only one that will drain + the output... The fix is to use TCSANOW which does + not wait. + + Telnetd was improperly setting/clearing the ISTRIP + flag in the c_lflag field, it should be using the + c_iflag field. + + When the child process of telnetd was opening the + slave side of the pty, it was re-setting the EXTPROC + bit too early, and some of the other initialization + code was wiping it out. This would cause telnetd + to go out of linemode and into single character mode. + + One instance of leaving linemode in telnetd forgot + to send a WILL ECHO to the client, the net result + would be that the user would see double character + echo. + + If the MODE was being changed several times very + quickly, telnetd could get out of sync with the + state changes and the returning acks; and wind up + being left in the wrong state. + +September 14, 1990: + + Switch the client to use getopt() for parsing the + argument list. The 4.3Reno getopt.c is included for + systems that don't have getopt(). + + Use the posix _POSIX_VDISABLE value for what value + to use when disabling special characters. If this + is undefined, it defaults to 0x3ff. + + For non-termio systems, TIOCSETP was being used to + change the state of the terminal. This causes the + input queue to be flushed, which we don't want. This + is now changed to TIOCSETN. + + Take out the "#ifdef notdef" around the code in the + server that generates a "sync" when the pty oputput + is flushed. The potential problem is that some older + telnet clients may go into an infinate loop when they + receive a "sync", if so, the server can be compiled + with "NO_URGENT" defined. + + Fix the client where it was setting/clearing the OPOST + bit in the c_lflag field, not the c_oflag field. + + Fix the client where it was setting/clearing the ISTRIP + bit in the c_lflag field, not the c_iflag field. (On + 4.3Reno, this is the ECHOPRT bit in the c_lflag field.) + The client also had its interpretation of WILL BINARY + and DO BINARY reversed. + + Fix a bug in client that would cause a core dump when + attempting to remove the last environment variable. + + In the client, there were a few places were switch() + was being passed a character, and if it was a negative + value, it could get sign extended, and not match + the 8 bit case statements. The fix is to and the + switch value with 0xff. + + Add a couple more printoption() calls in the client, I + don't think there are any more places were a telnet + command can be received and not printed out when + "options" is on. + + A new flag has been added to the client, "-a". Currently, + this just causes the USER name to be sent across, in + the future this may be used to signify that automatic + authentication is requested. + + The USER variable is now only sent by the client if + the "-a" or "-l user" options are explicity used, or + if the user explicitly asks for the "USER" environment + variable to be exported. In the server, if it receives + the "USER" environment variable, it won't print out the + banner message, so that only "Password:" will be printed. + This makes the symantics more like rlogin, and should be + more familiar to the user. (People are not used to + getting a banner message, and then getting just a + "Password:" prompt.) + + Re-vamp the code for starting up the child login + process. The code was getting ugly, and it was + hard to tell what was really going on. What we + do now is after the fork(), in the child: + 1) make sure we have no controlling tty + 2) open and initialize the tty + 3) do a setsid()/setpgrp() + 4) makes the tty our controlling tty. + On some systems, #2 makes the tty our controlling + tty, and #4 is a no-op. The parent process does + a gets rid of any controlling tty after the child + is fork()ed. + + Use the strdup() library routine in telnet, instead + of the local savestr() routine. If you don't have + strdup(), you need to define NO_STRDUP. + + Add support for ^T (SIGINFO/VSTATUS), found in the + 4.3Reno distribution. This maps to the AYT character. + You need a 4-line bugfix in the kernel to get this + to work properly: + + > *** tty_pty.c.ORG Tue Sep 11 09:41:53 1990 + > --- tty_pty.c Tue Sep 11 17:48:03 1990 + > *************** + > *** 609,613 **** + > if ((tp->t_lflag&NOFLSH) == 0) + > ttyflush(tp, FREAD|FWRITE); + > ! pgsignal(tp->t_pgrp, *(unsigned int *)data); + > return(0); + > } + > --- 609,616 ---- + > if ((tp->t_lflag&NOFLSH) == 0) + > ttyflush(tp, FREAD|FWRITE); + > ! pgsignal(tp->t_pgrp, *(unsigned int *)data, 1); + > ! if ((*(unsigned int *)data == SIGINFO) && + > ! ((tp->t_lflag&NOKERNINFO) == 0)) + > ! ttyinfo(tp); + > return(0); + > } + + The client is now smarter when setting the telnet escape + character; it only sets it to one of VEOL and VEOL2 if + one of them is undefined, and the other one is not already + defined to the telnet escape character. + + Handle TERMIOS systems that have seperate input and output + line speed settings imbedded in the flags. + + Many other minor bug fixes. + +June 20, 1990: + Re-organize makefiles and source tree. The telnet/Source + directory is now gone, and all the source that was in + telnet/Source is now just in the telnet directory. + + Seperate makefile for each system are now gone. There + are two makefiles, Makefile and Makefile.generic. + The "Makefile" has the definitions for the various + system, and "Makefile.generic" does all the work. + There is a variable called "WHAT" that is used to + specify what to make. For example, in the telnet + directory, you might say: + make 4.4bsd WHAT=clean + to clean out the directory. + + Add support for the ENVIRON and XDISPLOC options. + In order for the server to work, login has to have + the "-p" option to preserve environment variables. + + Add the SOFT_TAB and LIT_ECHO modes in the LINEMODE support. + + Add the "-l user" option to command line and open command + (This is passed through the ENVIRON option). + + Add the "-e" command line option, for setting the escape + character. + + Add the "-D", diagnostic, option to the server. This allows + the server to print out debug information, which is very + useful when trying to debug a telnet that doesn't have any + debugging ability. + + Turn off the literal next character when not in LINEMODE. + + Don't recognize ^Y locally, just pass it through. + + Make minor modifications for Sun4.0 and Sun4.1 + + Add support for both FORW1 and FORW2 characters. The + telnet escpape character is set to whichever of the + two is not being used. If both are in use, the escape + character is not set, so when in linemode the user will + have to follow the escape character with a or + +libtelnet/Makefile.4.4: +telnet/Makefile.4.4: +telnetd/Makefile.4.4: + These are the makefiles that can be used on a 4.3Reno + system when this software is installed in /usr/src/lib/libtelnet, + /usr/src/libexec/telnetd, and /usr/src/usr.bin/telnet. + + +The following TELNET options are supported: + + LINEMODE: + The LINEMODE option is supported as per RFC1116. The + FORWARDMASK option is not currently supported. + + BINARY: The client has the ability to turn on/off the BINARY + option in each direction. Turning on BINARY from + server to client causes the LITOUT bit to get set in + the terminal driver on both ends, turning on BINARY + from the client to the server causes the PASS8 bit + to get set in the terminal driver on both ends. + + TERMINAL-TYPE: + This is supported as per RFC1091. On the server side, + when a terminal type is received, termcap/terminfo + is consulted to determine if it is a known terminal + type. It keeps requesting terminal types until it + gets one that it recongnizes, or hits the end of the + list. The server side looks up the entry in the + termcap/terminfo data base, and generates a list of + names which it then passes one at a time to each + request for a terminal type, duplicating the last + entry in the list before cycling back to the beginning. + + NAWS: The Negotiate about Window Size, as per RFC 1073. + + TERMINAL-SPEED: + Implemented as per RFC 1079 + + TOGGLE-FLOW-CONTROL: + Implemented as per RFC 1080 + + TIMING-MARK: + As per RFC 860 + + SGA: As per RFC 858 + + ECHO: As per RFC 857 + + LOGOUT: As per RFC 727 + + STATUS: + The server will send its current status upon + request. It does not ask for the clients status. + The client will request the servers current status + from the "send getstatus" command. + + ENVIRON: + This option is currently being defined by the IETF + Telnet Working Group, and an RFC has not yet been + issued, but should be in the near future... + + X-DISPLAY-LOCATION: + This functionality can be done through the ENVIRON + option, it is added here for completeness. + + AUTHENTICATION: + This option is currently being defined by the IETF + Telnet Working Group, and an RFC has not yet been + issued. The basic framework is pretty much decided, + but the definitions for the specific authentication + schemes is still in a state of flux. + + ENCRYPTION: + This option is currently being defined by the IETF + Telnet Working Group, and an RFC has not yet been + issued. The draft RFC is still in a state of flux, + so this code may change in the future. diff --git a/telnet.tproj/authenc.c b/telnet.tproj/authenc.c new file mode 100644 index 0000000..9d5330d --- /dev/null +++ b/telnet.tproj/authenc.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)authenc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#include +#include +#include +#include + +#include "general.h" +#include "ring.h" +#include "externs.h" +#include "defines.h" +#include "types.h" + + int +net_write(str, len) + unsigned char *str; + int len; +{ + if (NETROOM() > len) { + ring_supply_data(&netoring, str, len); + if (str[0] == IAC && str[1] == SE) + printsub('>', &str[2], len-2); + return(len); + } + return(0); +} + + void +net_encrypt() +{ +#ifdef ENCRYPTION + if (encrypt_output) + ring_encrypt(&netoring, encrypt_output); + else + ring_clearto(&netoring); +#endif /* ENCRYPTION */ +} + + int +telnet_spin() +{ + return(-1); +} + + char * +telnet_getenv(val) + char *val; +{ + return((char *)env_getvalue((unsigned char *)val)); +} + + char * +telnet_gets(prompt, result, length, echo) + char *prompt; + char *result; + int length; + int echo; +{ + extern char *getpass(); + extern int globalmode; + int om = globalmode; + char *res; + + TerminalNewMode(-1); + if (echo) { + printf("%s", prompt); + res = fgets(result, length, stdin); + } else if (res = getpass(prompt)) { + strncpy(result, res, length); + res = result; + } + TerminalNewMode(om); + return(res); +} +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ diff --git a/telnet.tproj/commands.c b/telnet.tproj/commands.c new file mode 100644 index 0000000..903bda3 --- /dev/null +++ b/telnet.tproj/commands.c @@ -0,0 +1,2990 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)commands.c 8.4 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#if defined(unix) || defined(__APPLE__) +#include +#if defined(CRAY) || defined(sysV88) +#include +#endif +#include +#else +#include +#endif /* defined(unix) || defined(__APPLE__) */ +#include +#include +#ifdef CRAY +#include +#endif /* CRAY */ + +#include +#include +#include +#include +#if !defined(__APPLE__) +#include +#endif +#include + +#include + +#include "general.h" + +#include "ring.h" + +#include "externs.h" +#include "defines.h" +#include "types.h" + +#if !defined(CRAY) && !defined(sysV88) +#include +# if (defined(vax) || defined(tahoe) || defined(hp300)) && !defined(ultrix) +# include +# endif /* vax */ +#endif /* !defined(CRAY) && !defined(sysV88) */ +#include + + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif MAXHOSTNAMELEN + +#if defined(IPPROTO_IP) && defined(IP_TOS) +int tos = -1; +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + +char *hostname; +static char _hostname[MAXHOSTNAMELEN]; + +extern char *getenv(); + +extern int isprefix(); +extern char **genget(); +extern int Ambiguous(); + +typedef int (*intrtn_t)(); +#if __STDC__ +static call(intrtn_t routine, ...); +#else +static call(); +#endif + +typedef struct { + char *name; /* command name */ + char *help; /* help string (NULL for no help) */ + int (*handler)(); /* routine which executes command */ + int needconnect; /* Do we need to be connected to execute? */ +} Command; + +static char line[256]; +static char saveline[256]; +static int margc; +static char *margv[20]; + + static void +makeargv() +{ + register char *cp, *cp2, c; + register char **argp = margv; + + margc = 0; + cp = line; + if (*cp == '!') { /* Special case shell escape */ + strcpy(saveline, line); /* save for shell command */ + *argp++ = "!"; /* No room in string to get this */ + margc++; + cp++; + } + while (c = *cp) { + register int inquote = 0; + while (isspace(c)) + c = *++cp; + if (c == '\0') + break; + *argp++ = cp; + margc += 1; + for (cp2 = cp; c != '\0'; c = *++cp) { + if (inquote) { + if (c == inquote) { + inquote = 0; + continue; + } + } else { + if (c == '\\') { + if ((c = *++cp) == '\0') + break; + } else if (c == '"') { + inquote = '"'; + continue; + } else if (c == '\'') { + inquote = '\''; + continue; + } else if (isspace(c)) + break; + } + *cp2++ = c; + } + *cp2 = '\0'; + if (c == '\0') + break; + cp++; + } + *argp++ = 0; +} + +/* + * Make a character string into a number. + * + * Todo: 1. Could take random integers (12, 0x12, 012, 0b1). + */ + + static +special(s) + register char *s; +{ + register char c; + char b; + + switch (*s) { + case '^': + b = *++s; + if (b == '?') { + c = b | 0x40; /* DEL */ + } else { + c = b & 0x1f; + } + break; + default: + c = *s; + break; + } + return c; +} + +/* + * Construct a control character sequence + * for a special character. + */ + static char * +control(c) + register cc_t c; +{ + static char buf[5]; + /* + * The only way I could get the Sun 3.5 compiler + * to shut up about + * if ((unsigned int)c >= 0x80) + * was to assign "c" to an unsigned int variable... + * Arggg.... + */ + register unsigned int uic = (unsigned int)c; + + if (uic == 0x7f) + return ("^?"); + if (c == (cc_t)_POSIX_VDISABLE) { + return "off"; + } + if (uic >= 0x80) { + buf[0] = '\\'; + buf[1] = ((c>>6)&07) + '0'; + buf[2] = ((c>>3)&07) + '0'; + buf[3] = (c&07) + '0'; + buf[4] = 0; + } else if (uic >= 0x20) { + buf[0] = c; + buf[1] = 0; + } else { + buf[0] = '^'; + buf[1] = '@'+c; + buf[2] = 0; + } + return (buf); +} + + + +/* + * The following are data structures and routines for + * the "send" command. + * + */ + +struct sendlist { + char *name; /* How user refers to it (case independent) */ + char *help; /* Help information (0 ==> no help) */ + int needconnect; /* Need to be connected */ + int narg; /* Number of arguments */ + int (*handler)(); /* Routine to perform (for special ops) */ + int nbyte; /* Number of bytes to send this command */ + int what; /* Character to be sent (<0 ==> special) */ +}; + + +static int + send_esc P((void)), + send_help P((void)), + send_docmd P((char *)), + send_dontcmd P((char *)), + send_willcmd P((char *)), + send_wontcmd P((char *)); + +static struct sendlist Sendlist[] = { + { "ao", "Send Telnet Abort output", 1, 0, 0, 2, AO }, + { "ayt", "Send Telnet 'Are You There'", 1, 0, 0, 2, AYT }, + { "brk", "Send Telnet Break", 1, 0, 0, 2, BREAK }, + { "break", 0, 1, 0, 0, 2, BREAK }, + { "ec", "Send Telnet Erase Character", 1, 0, 0, 2, EC }, + { "el", "Send Telnet Erase Line", 1, 0, 0, 2, EL }, + { "escape", "Send current escape character", 1, 0, send_esc, 1, 0 }, + { "ga", "Send Telnet 'Go Ahead' sequence", 1, 0, 0, 2, GA }, + { "ip", "Send Telnet Interrupt Process", 1, 0, 0, 2, IP }, + { "intp", 0, 1, 0, 0, 2, IP }, + { "interrupt", 0, 1, 0, 0, 2, IP }, + { "intr", 0, 1, 0, 0, 2, IP }, + { "nop", "Send Telnet 'No operation'", 1, 0, 0, 2, NOP }, + { "eor", "Send Telnet 'End of Record'", 1, 0, 0, 2, EOR }, + { "abort", "Send Telnet 'Abort Process'", 1, 0, 0, 2, ABORT }, + { "susp", "Send Telnet 'Suspend Process'", 1, 0, 0, 2, SUSP }, + { "eof", "Send Telnet End of File Character", 1, 0, 0, 2, xEOF }, + { "synch", "Perform Telnet 'Synch operation'", 1, 0, dosynch, 2, 0 }, + { "getstatus", "Send request for STATUS", 1, 0, get_status, 6, 0 }, + { "?", "Display send options", 0, 0, send_help, 0, 0 }, + { "help", 0, 0, 0, send_help, 0, 0 }, + { "do", 0, 0, 1, send_docmd, 3, 0 }, + { "dont", 0, 0, 1, send_dontcmd, 3, 0 }, + { "will", 0, 0, 1, send_willcmd, 3, 0 }, + { "wont", 0, 0, 1, send_wontcmd, 3, 0 }, + { 0 } +}; + +#define GETSEND(name) ((struct sendlist *) genget(name, (char **) Sendlist, \ + sizeof(struct sendlist))) + + static int +sendcmd(argc, argv) + int argc; + char **argv; +{ + int count; /* how many bytes we are going to need to send */ + int i; + int question = 0; /* was at least one argument a question */ + struct sendlist *s; /* pointer to current command */ + int success = 0; + int needconnect = 0; + + if (argc < 2) { + printf("need at least one argument for 'send' command\n"); + printf("'send ?' for help\n"); + return 0; + } + /* + * First, validate all the send arguments. + * In addition, we see how much space we are going to need, and + * whether or not we will be doing a "SYNCH" operation (which + * flushes the network queue). + */ + count = 0; + for (i = 1; i < argc; i++) { + s = GETSEND(argv[i]); + if (s == 0) { + printf("Unknown send argument '%s'\n'send ?' for help.\n", + argv[i]); + return 0; + } else if (Ambiguous(s)) { + printf("Ambiguous send argument '%s'\n'send ?' for help.\n", + argv[i]); + return 0; + } + if (i + s->narg >= argc) { + fprintf(stderr, + "Need %d argument%s to 'send %s' command. 'send %s ?' for help.\n", + s->narg, s->narg == 1 ? "" : "s", s->name, s->name); + return 0; + } + count += s->nbyte; + if (s->handler == send_help) { + send_help(); + return 0; + } + + i += s->narg; + needconnect += s->needconnect; + } + if (!connected && needconnect) { + printf("?Need to be connected first.\n"); + printf("'send ?' for help\n"); + return 0; + } + /* Now, do we have enough room? */ + if (NETROOM() < count) { + printf("There is not enough room in the buffer TO the network\n"); + printf("to process your request. Nothing will be done.\n"); + printf("('send synch' will throw away most data in the network\n"); + printf("buffer, if this might help.)\n"); + return 0; + } + /* OK, they are all OK, now go through again and actually send */ + count = 0; + for (i = 1; i < argc; i++) { + if ((s = GETSEND(argv[i])) == 0) { + fprintf(stderr, "Telnet 'send' error - argument disappeared!\n"); + (void) quit(); + /*NOTREACHED*/ + } + if (s->handler) { + count++; + success += (*s->handler)((s->narg > 0) ? argv[i+1] : 0, + (s->narg > 1) ? argv[i+2] : 0); + i += s->narg; + } else { + NET2ADD(IAC, s->what); + printoption("SENT", IAC, s->what); + } + } + return (count == success); +} + + static int +send_esc() +{ + NETADD(escape); + return 1; +} + + static int +send_docmd(name) + char *name; +{ + return(send_tncmd(send_do, "do", name)); +} + + static int +send_dontcmd(name) + char *name; +{ + return(send_tncmd(send_dont, "dont", name)); +} + static int +send_willcmd(name) + char *name; +{ + return(send_tncmd(send_will, "will", name)); +} + static int +send_wontcmd(name) + char *name; +{ + return(send_tncmd(send_wont, "wont", name)); +} + + int +send_tncmd(func, cmd, name) + void (*func)(); + char *cmd, *name; +{ + char **cpp; + extern char *telopts[]; + register int val = 0; + + if (isprefix(name, "help") || isprefix(name, "?")) { + register int col, len; + + printf("Usage: send %s \n", cmd); + printf("\"value\" must be from 0 to 255\n"); + printf("Valid options are:\n\t"); + + col = 8; + for (cpp = telopts; *cpp; cpp++) { + len = strlen(*cpp) + 3; + if (col + len > 65) { + printf("\n\t"); + col = 8; + } + printf(" \"%s\"", *cpp); + col += len; + } + printf("\n"); + return 0; + } + cpp = (char **)genget(name, telopts, sizeof(char *)); + if (Ambiguous(cpp)) { + fprintf(stderr,"'%s': ambiguous argument ('send %s ?' for help).\n", + name, cmd); + return 0; + } + if (cpp) { + val = cpp - telopts; + } else { + register char *cp = name; + + while (*cp >= '0' && *cp <= '9') { + val *= 10; + val += *cp - '0'; + cp++; + } + if (*cp != 0) { + fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n", + name, cmd); + return 0; + } else if (val < 0 || val > 255) { + fprintf(stderr, "'%s': bad value ('send %s ?' for help).\n", + name, cmd); + return 0; + } + } + if (!connected) { + printf("?Need to be connected first.\n"); + return 0; + } + (*func)(val, 1); + return 1; +} + + static int +send_help() +{ + struct sendlist *s; /* pointer to current command */ + for (s = Sendlist; s->name; s++) { + if (s->help) + printf("%-15s %s\n", s->name, s->help); + } + return(0); +} + +/* + * The following are the routines and data structures referred + * to by the arguments to the "toggle" command. + */ + + static int +lclchars() +{ + donelclchars = 1; + return 1; +} + + static int +togdebug() +{ +#ifndef NOT43 + if (net > 0 && + (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) { + perror("setsockopt (SO_DEBUG)"); + } +#else /* NOT43 */ + if (debug) { + if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) + perror("setsockopt (SO_DEBUG)"); + } else + printf("Cannot turn off socket debugging\n"); +#endif /* NOT43 */ + return 1; +} + + + static int +togcrlf() +{ + if (crlf) { + printf("Will send carriage returns as telnet .\n"); + } else { + printf("Will send carriage returns as telnet .\n"); + } + return 1; +} + +int binmode; + + static int +togbinary(val) + int val; +{ + donebinarytoggle = 1; + + if (val >= 0) { + binmode = val; + } else { + if (my_want_state_is_will(TELOPT_BINARY) && + my_want_state_is_do(TELOPT_BINARY)) { + binmode = 1; + } else if (my_want_state_is_wont(TELOPT_BINARY) && + my_want_state_is_dont(TELOPT_BINARY)) { + binmode = 0; + } + val = binmode ? 0 : 1; + } + + if (val == 1) { + if (my_want_state_is_will(TELOPT_BINARY) && + my_want_state_is_do(TELOPT_BINARY)) { + printf("Already operating in binary mode with remote host.\n"); + } else { + printf("Negotiating binary mode with remote host.\n"); + tel_enter_binary(3); + } + } else { + if (my_want_state_is_wont(TELOPT_BINARY) && + my_want_state_is_dont(TELOPT_BINARY)) { + printf("Already in network ascii mode with remote host.\n"); + } else { + printf("Negotiating network ascii mode with remote host.\n"); + tel_leave_binary(3); + } + } + return 1; +} + + static int +togrbinary(val) + int val; +{ + donebinarytoggle = 1; + + if (val == -1) + val = my_want_state_is_do(TELOPT_BINARY) ? 0 : 1; + + if (val == 1) { + if (my_want_state_is_do(TELOPT_BINARY)) { + printf("Already receiving in binary mode.\n"); + } else { + printf("Negotiating binary mode on input.\n"); + tel_enter_binary(1); + } + } else { + if (my_want_state_is_dont(TELOPT_BINARY)) { + printf("Already receiving in network ascii mode.\n"); + } else { + printf("Negotiating network ascii mode on input.\n"); + tel_leave_binary(1); + } + } + return 1; +} + + static int +togxbinary(val) + int val; +{ + donebinarytoggle = 1; + + if (val == -1) + val = my_want_state_is_will(TELOPT_BINARY) ? 0 : 1; + + if (val == 1) { + if (my_want_state_is_will(TELOPT_BINARY)) { + printf("Already transmitting in binary mode.\n"); + } else { + printf("Negotiating binary mode on output.\n"); + tel_enter_binary(2); + } + } else { + if (my_want_state_is_wont(TELOPT_BINARY)) { + printf("Already transmitting in network ascii mode.\n"); + } else { + printf("Negotiating network ascii mode on output.\n"); + tel_leave_binary(2); + } + } + return 1; +} + + +static int togglehelp P((void)); +#if defined(AUTHENTICATION) +extern int auth_togdebug P((int)); +#endif +#ifdef ENCRYPTION +extern int EncryptAutoEnc P((int)); +extern int EncryptAutoDec P((int)); +extern int EncryptDebug P((int)); +extern int EncryptVerbose P((int)); +#endif /* ENCRYPTION */ + +struct togglelist { + char *name; /* name of toggle */ + char *help; /* help message */ + int (*handler)(); /* routine to do actual setting */ + int *variable; + char *actionexplanation; +}; + +static struct togglelist Togglelist[] = { + { "autoflush", + "flushing of output when sending interrupt characters", + 0, + &autoflush, + "flush output when sending interrupt characters" }, + { "autosynch", + "automatic sending of interrupt characters in urgent mode", + 0, + &autosynch, + "send interrupt characters in urgent mode" }, +#if defined(AUTHENTICATION) + { "autologin", + "automatic sending of login and/or authentication info", + 0, + &autologin, + "send login name and/or authentication information" }, + { "authdebug", + "Toggle authentication debugging", + auth_togdebug, + 0, + "print authentication debugging information" }, +#endif +#ifdef ENCRYPTION + { "autoencrypt", + "automatic encryption of data stream", + EncryptAutoEnc, + 0, + "automatically encrypt output" }, + { "autodecrypt", + "automatic decryption of data stream", + EncryptAutoDec, + 0, + "automatically decrypt input" }, + { "verbose_encrypt", + "Toggle verbose encryption output", + EncryptVerbose, + 0, + "print verbose encryption output" }, + { "encdebug", + "Toggle encryption debugging", + EncryptDebug, + 0, + "print encryption debugging information" }, +#endif /* ENCRYPTION */ + { "skiprc", + "don't read ~/.telnetrc file", + 0, + &skiprc, + "skip reading of ~/.telnetrc file" }, + { "binary", + "sending and receiving of binary data", + togbinary, + 0, + 0 }, + { "inbinary", + "receiving of binary data", + togrbinary, + 0, + 0 }, + { "outbinary", + "sending of binary data", + togxbinary, + 0, + 0 }, + { "crlf", + "sending carriage returns as telnet ", + togcrlf, + &crlf, + 0 }, + { "crmod", + "mapping of received carriage returns", + 0, + &crmod, + "map carriage return on output" }, + { "localchars", + "local recognition of certain control characters", + lclchars, + &localchars, + "recognize certain control characters" }, + { " ", "", 0 }, /* empty line */ +#if (defined(unix) || defined(__APPLE__)) && defined(TN3270) + { "apitrace", + "(debugging) toggle tracing of API transactions", + 0, + &apitrace, + "trace API transactions" }, + { "cursesdata", + "(debugging) toggle printing of hexadecimal curses data", + 0, + &cursesdata, + "print hexadecimal representation of curses data" }, +#endif /* (defined(unix) || defined(__APPLE__)) && defined(TN3270) */ + { "debug", + "debugging", + togdebug, + &debug, + "turn on socket level debugging" }, + { "netdata", + "printing of hexadecimal network data (debugging)", + 0, + &netdata, + "print hexadecimal representation of network traffic" }, + { "prettydump", + "output of \"netdata\" to user readable format (debugging)", + 0, + &prettydump, + "print user readable output for \"netdata\"" }, + { "options", + "viewing of options processing (debugging)", + 0, + &showoptions, + "show option processing" }, +#if defined(unix) || defined(__APPLE__) + { "termdata", + "(debugging) toggle printing of hexadecimal terminal data", + 0, + &termdata, + "print hexadecimal representation of terminal traffic" }, +#endif /* defined(unix) || defined(__APPLE__) */ + { "?", + 0, + togglehelp }, + { "help", + 0, + togglehelp }, + { 0 } +}; + + static int +togglehelp() +{ + struct togglelist *c; + + for (c = Togglelist; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s toggle %s\n", c->name, c->help); + else + printf("\n"); + } + } + printf("\n"); + printf("%-15s %s\n", "?", "display help information"); + return 0; +} + + static void +settogglehelp(set) + int set; +{ + struct togglelist *c; + + for (c = Togglelist; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s %s\n", c->name, set ? "enable" : "disable", + c->help); + else + printf("\n"); + } + } +} + +#define GETTOGGLE(name) (struct togglelist *) \ + genget(name, (char **) Togglelist, sizeof(struct togglelist)) + + static int +toggle(argc, argv) + int argc; + char *argv[]; +{ + int retval = 1; + char *name; + struct togglelist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'toggle' command. 'toggle ?' for help.\n"); + return 0; + } + argc--; + argv++; + while (argc--) { + name = *argv++; + c = GETTOGGLE(name); + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('toggle ?' for help).\n", + name); + return 0; + } else if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('toggle ?' for help).\n", + name); + return 0; + } else { + if (c->variable) { + *c->variable = !*c->variable; /* invert it */ + if (c->actionexplanation) { + printf("%s %s.\n", *c->variable? "Will" : "Won't", + c->actionexplanation); + } + } + if (c->handler) { + retval &= (*c->handler)(-1); + } + } + } + return retval; +} + +/* + * The following perform the "set" command. + */ + +#ifdef USE_TERMIO +struct termio new_tc = { 0 }; +#endif + +struct setlist { + char *name; /* name */ + char *help; /* help information */ + void (*handler)(); + cc_t *charp; /* where it is located at */ +}; + +static struct setlist Setlist[] = { +#ifdef KLUDGELINEMODE + { "echo", "character to toggle local echoing on/off", 0, &echoc }, +#endif + { "escape", "character to escape back to telnet command mode", 0, &escape }, + { "rlogin", "rlogin escape character", 0, &rlogin }, + { "tracefile", "file to write trace information to", SetNetTrace, (cc_t *)NetTraceFile}, + { " ", "" }, + { " ", "The following need 'localchars' to be toggled true", 0, 0 }, + { "flushoutput", "character to cause an Abort Output", 0, termFlushCharp }, + { "interrupt", "character to cause an Interrupt Process", 0, termIntCharp }, + { "quit", "character to cause an Abort process", 0, termQuitCharp }, + { "eof", "character to cause an EOF ", 0, termEofCharp }, + { " ", "" }, + { " ", "The following are for local editing in linemode", 0, 0 }, + { "erase", "character to use to erase a character", 0, termEraseCharp }, + { "kill", "character to use to erase a line", 0, termKillCharp }, + { "lnext", "character to use for literal next", 0, termLiteralNextCharp }, + { "susp", "character to cause a Suspend Process", 0, termSuspCharp }, + { "reprint", "character to use for line reprint", 0, termRprntCharp }, + { "worderase", "character to use to erase a word", 0, termWerasCharp }, + { "start", "character to use for XON", 0, termStartCharp }, + { "stop", "character to use for XOFF", 0, termStopCharp }, + { "forw1", "alternate end of line character", 0, termForw1Charp }, + { "forw2", "alternate end of line character", 0, termForw2Charp }, + { "ayt", "alternate AYT character", 0, termAytCharp }, + { 0 } +}; + +#if defined(CRAY) && !defined(__STDC__) +/* Work around compiler bug in pcc 4.1.5 */ + void +_setlist_init() +{ +#ifndef KLUDGELINEMODE +#define N 5 +#else +#define N 6 +#endif + Setlist[N+0].charp = &termFlushChar; + Setlist[N+1].charp = &termIntChar; + Setlist[N+2].charp = &termQuitChar; + Setlist[N+3].charp = &termEofChar; + Setlist[N+6].charp = &termEraseChar; + Setlist[N+7].charp = &termKillChar; + Setlist[N+8].charp = &termLiteralNextChar; + Setlist[N+9].charp = &termSuspChar; + Setlist[N+10].charp = &termRprntChar; + Setlist[N+11].charp = &termWerasChar; + Setlist[N+12].charp = &termStartChar; + Setlist[N+13].charp = &termStopChar; + Setlist[N+14].charp = &termForw1Char; + Setlist[N+15].charp = &termForw2Char; + Setlist[N+16].charp = &termAytChar; +#undef N +} +#endif /* defined(CRAY) && !defined(__STDC__) */ + + static struct setlist * +getset(name) + char *name; +{ + return (struct setlist *) + genget(name, (char **) Setlist, sizeof(struct setlist)); +} + + void +set_escape_char(s) + char *s; +{ + if (rlogin != _POSIX_VDISABLE) { + rlogin = (s && *s) ? special(s) : _POSIX_VDISABLE; + printf("Telnet rlogin escape character is '%s'.\n", + control(rlogin)); + } else { + escape = (s && *s) ? special(s) : _POSIX_VDISABLE; + printf("Telnet escape character is '%s'.\n", control(escape)); + } +} + + static int +setcmd(argc, argv) + int argc; + char *argv[]; +{ + int value; + struct setlist *ct; + struct togglelist *c; + + if (argc < 2 || argc > 3) { + printf("Format is 'set Name Value'\n'set ?' for help.\n"); + return 0; + } + if ((argc == 2) && (isprefix(argv[1], "?") || isprefix(argv[1], "help"))) { + for (ct = Setlist; ct->name; ct++) + printf("%-15s %s\n", ct->name, ct->help); + printf("\n"); + settogglehelp(1); + printf("%-15s %s\n", "?", "display help information"); + return 0; + } + + ct = getset(argv[1]); + if (ct == 0) { + c = GETTOGGLE(argv[1]); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('set ?' for help).\n", + argv[1]); + return 0; + } else if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", + argv[1]); + return 0; + } + if (c->variable) { + if ((argc == 2) || (strcmp("on", argv[2]) == 0)) + *c->variable = 1; + else if (strcmp("off", argv[2]) == 0) + *c->variable = 0; + else { + printf("Format is 'set togglename [on|off]'\n'set ?' for help.\n"); + return 0; + } + if (c->actionexplanation) { + printf("%s %s.\n", *c->variable? "Will" : "Won't", + c->actionexplanation); + } + } + if (c->handler) + (*c->handler)(1); + } else if (argc != 3) { + printf("Format is 'set Name Value'\n'set ?' for help.\n"); + return 0; + } else if (Ambiguous(ct)) { + fprintf(stderr, "'%s': ambiguous argument ('set ?' for help).\n", + argv[1]); + return 0; + } else if (ct->handler) { + (*ct->handler)(argv[2]); + printf("%s set to \"%s\".\n", ct->name, (char *)ct->charp); + } else { + if (strcmp("off", argv[2])) { + value = special(argv[2]); + } else { + value = _POSIX_VDISABLE; + } + *(ct->charp) = (cc_t)value; + printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); + } + slc_check(); + return 1; +} + + static int +unsetcmd(argc, argv) + int argc; + char *argv[]; +{ + struct setlist *ct; + struct togglelist *c; + register char *name; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'unset' command. 'unset ?' for help.\n"); + return 0; + } + if (isprefix(argv[1], "?") || isprefix(argv[1], "help")) { + for (ct = Setlist; ct->name; ct++) + printf("%-15s %s\n", ct->name, ct->help); + printf("\n"); + settogglehelp(0); + printf("%-15s %s\n", "?", "display help information"); + return 0; + } + + argc--; + argv++; + while (argc--) { + name = *argv++; + ct = getset(name); + if (ct == 0) { + c = GETTOGGLE(name); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('unset ?' for help).\n", + name); + return 0; + } else if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", + name); + return 0; + } + if (c->variable) { + *c->variable = 0; + if (c->actionexplanation) { + printf("%s %s.\n", *c->variable? "Will" : "Won't", + c->actionexplanation); + } + } + if (c->handler) + (*c->handler)(0); + } else if (Ambiguous(ct)) { + fprintf(stderr, "'%s': ambiguous argument ('unset ?' for help).\n", + name); + return 0; + } else if (ct->handler) { + (*ct->handler)(0); + printf("%s reset to \"%s\".\n", ct->name, (char *)ct->charp); + } else { + *(ct->charp) = _POSIX_VDISABLE; + printf("%s character is '%s'.\n", ct->name, control(*(ct->charp))); + } + } + return 1; +} + +/* + * The following are the data structures and routines for the + * 'mode' command. + */ +#ifdef KLUDGELINEMODE +extern int kludgelinemode; + + static int +dokludgemode() +{ + kludgelinemode = 1; + send_wont(TELOPT_LINEMODE, 1); + send_dont(TELOPT_SGA, 1); + send_dont(TELOPT_ECHO, 1); +} +#endif + + static int +dolinemode() +{ +#ifdef KLUDGELINEMODE + if (kludgelinemode) + send_dont(TELOPT_SGA, 1); +#endif + send_will(TELOPT_LINEMODE, 1); + send_dont(TELOPT_ECHO, 1); + return 1; +} + + static int +docharmode() +{ +#ifdef KLUDGELINEMODE + if (kludgelinemode) + send_do(TELOPT_SGA, 1); + else +#endif + send_wont(TELOPT_LINEMODE, 1); + send_do(TELOPT_ECHO, 1); + return 1; +} + + static int +dolmmode(bit, on) + int bit, on; +{ + unsigned char c; + extern int linemode; + + if (my_want_state_is_wont(TELOPT_LINEMODE)) { + printf("?Need to have LINEMODE option enabled first.\n"); + printf("'mode ?' for help.\n"); + return 0; + } + + if (on) + c = (linemode | bit); + else + c = (linemode & ~bit); + lm_mode(&c, 1, 1); + return 1; +} + + int +setmode(bit) +{ + return dolmmode(bit, 1); +} + + int +clearmode(bit) +{ + return dolmmode(bit, 0); +} + +struct modelist { + char *name; /* command name */ + char *help; /* help string */ + int (*handler)(); /* routine which executes command */ + int needconnect; /* Do we need to be connected to execute? */ + int arg1; +}; + +extern int modehelp(); + +static struct modelist ModeList[] = { + { "character", "Disable LINEMODE option", docharmode, 1 }, +#ifdef KLUDGELINEMODE + { "", "(or disable obsolete line-by-line mode)", 0 }, +#endif + { "line", "Enable LINEMODE option", dolinemode, 1 }, +#ifdef KLUDGELINEMODE + { "", "(or enable obsolete line-by-line mode)", 0 }, +#endif + { "", "", 0 }, + { "", "These require the LINEMODE option to be enabled", 0 }, + { "isig", "Enable signal trapping", setmode, 1, MODE_TRAPSIG }, + { "+isig", 0, setmode, 1, MODE_TRAPSIG }, + { "-isig", "Disable signal trapping", clearmode, 1, MODE_TRAPSIG }, + { "edit", "Enable character editing", setmode, 1, MODE_EDIT }, + { "+edit", 0, setmode, 1, MODE_EDIT }, + { "-edit", "Disable character editing", clearmode, 1, MODE_EDIT }, + { "softtabs", "Enable tab expansion", setmode, 1, MODE_SOFT_TAB }, + { "+softtabs", 0, setmode, 1, MODE_SOFT_TAB }, + { "-softtabs", "Disable character editing", clearmode, 1, MODE_SOFT_TAB }, + { "litecho", "Enable literal character echo", setmode, 1, MODE_LIT_ECHO }, + { "+litecho", 0, setmode, 1, MODE_LIT_ECHO }, + { "-litecho", "Disable literal character echo", clearmode, 1, MODE_LIT_ECHO }, + { "help", 0, modehelp, 0 }, +#ifdef KLUDGELINEMODE + { "kludgeline", 0, dokludgemode, 1 }, +#endif + { "", "", 0 }, + { "?", "Print help information", modehelp, 0 }, + { 0 }, +}; + + + int +modehelp() +{ + struct modelist *mt; + + printf("format is: 'mode Mode', where 'Mode' is one of:\n\n"); + for (mt = ModeList; mt->name; mt++) { + if (mt->help) { + if (*mt->help) + printf("%-15s %s\n", mt->name, mt->help); + else + printf("\n"); + } + } + return 0; +} + +#define GETMODECMD(name) (struct modelist *) \ + genget(name, (char **) ModeList, sizeof(struct modelist)) + + static int +modecmd(argc, argv) + int argc; + char *argv[]; +{ + struct modelist *mt; + + if (argc != 2) { + printf("'mode' command requires an argument\n"); + printf("'mode ?' for help.\n"); + } else if ((mt = GETMODECMD(argv[1])) == 0) { + fprintf(stderr, "Unknown mode '%s' ('mode ?' for help).\n", argv[1]); + } else if (Ambiguous(mt)) { + fprintf(stderr, "Ambiguous mode '%s' ('mode ?' for help).\n", argv[1]); + } else if (mt->needconnect && !connected) { + printf("?Need to be connected first.\n"); + printf("'mode ?' for help.\n"); + } else if (mt->handler) { + return (*mt->handler)(mt->arg1); + } + return 0; +} + +/* + * The following data structures and routines implement the + * "display" command. + */ + + static int +display(argc, argv) + int argc; + char *argv[]; +{ + struct togglelist *tl; + struct setlist *sl; + +#define dotog(tl) if (tl->variable && tl->actionexplanation) { \ + if (*tl->variable) { \ + printf("will"); \ + } else { \ + printf("won't"); \ + } \ + printf(" %s.\n", tl->actionexplanation); \ + } + +#define doset(sl) if (sl->name && *sl->name != ' ') { \ + if (sl->handler == 0) \ + printf("%-15s [%s]\n", sl->name, control(*sl->charp)); \ + else \ + printf("%-15s \"%s\"\n", sl->name, (char *)sl->charp); \ + } + + if (argc == 1) { + for (tl = Togglelist; tl->name; tl++) { + dotog(tl); + } + printf("\n"); + for (sl = Setlist; sl->name; sl++) { + doset(sl); + } + } else { + int i; + + for (i = 1; i < argc; i++) { + sl = getset(argv[i]); + tl = GETTOGGLE(argv[i]); + if (Ambiguous(sl) || Ambiguous(tl)) { + printf("?Ambiguous argument '%s'.\n", argv[i]); + return 0; + } else if (!sl && !tl) { + printf("?Unknown argument '%s'.\n", argv[i]); + return 0; + } else { + if (tl) { + dotog(tl); + } + if (sl) { + doset(sl); + } + } + } + } +/*@*/optionstatus(); +#ifdef ENCRYPTION + EncryptStatus(); +#endif /* ENCRYPTION */ + return 1; +#undef doset +#undef dotog +} + +/* + * The following are the data structures, and many of the routines, + * relating to command processing. + */ + +/* + * Set the escape character. + */ + static int +setescape(argc, argv) + int argc; + char *argv[]; +{ + register char *arg; + char buf[50]; + + printf( + "Deprecated usage - please use 'set escape%s%s' in the future.\n", + (argc > 2)? " ":"", (argc > 2)? argv[1]: ""); + if (argc > 2) + arg = argv[1]; + else { + printf("new escape character: "); + (void) fgets(buf, sizeof(buf), stdin); + arg = buf; + } + if (arg[0] != '\0') + escape = arg[0]; + if (!In3270) { + printf("Escape character is '%s'.\n", control(escape)); + } + (void) fflush(stdout); + return 1; +} + + /*VARARGS*/ + static int +togcrmod() +{ + crmod = !crmod; + printf("Deprecated usage - please use 'toggle crmod' in the future.\n"); + printf("%s map carriage return on output.\n", crmod ? "Will" : "Won't"); + (void) fflush(stdout); + return 1; +} + + /*VARARGS*/ + int +suspend() +{ +#ifdef SIGTSTP + setcommandmode(); + { + long oldrows, oldcols, newrows, newcols, err; + + err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + (void) kill(0, SIGTSTP); + /* + * If we didn't get the window size before the SUSPEND, but we + * can get them now (?), then send the NAWS to make sure that + * we are set up for the right window size. + */ + if (TerminalWindowSize(&newrows, &newcols) && connected && + (err || ((oldrows != newrows) || (oldcols != newcols)))) { + sendnaws(); + } + } + /* reget parameters in case they were changed */ + TerminalSaveState(); + setconnmode(0); +#else + printf("Suspend is not supported. Try the '!' command instead\n"); +#endif + return 1; +} + +#if !defined(TN3270) + /*ARGSUSED*/ + int +shell(argc, argv) + int argc; + char *argv[]; +{ + long oldrows, oldcols, newrows, newcols, err; + + setcommandmode(); + + err = (TerminalWindowSize(&oldrows, &oldcols) == 0) ? 1 : 0; + switch(vfork()) { + case -1: + perror("Fork failed\n"); + break; + + case 0: + { + /* + * Fire up the shell in the child. + */ + register char *shellp, *shellname; + extern char *strrchr(); + + shellp = getenv("SHELL"); + if (shellp == NULL) + shellp = "/bin/sh"; + if ((shellname = strrchr(shellp, '/')) == 0) + shellname = shellp; + else + shellname++; + if (argc > 1) + execl(shellp, shellname, "-c", &saveline[1], 0); + else + execl(shellp, shellname, 0); + perror("Execl"); + _exit(1); + } + default: + (void)wait((int *)0); /* Wait for the shell to complete */ + + if (TerminalWindowSize(&newrows, &newcols) && connected && + (err || ((oldrows != newrows) || (oldcols != newcols)))) { + sendnaws(); + } + break; + } + return 1; +} +#else /* !defined(TN3270) */ +extern int shell(); +#endif /* !defined(TN3270) */ + + /*VARARGS*/ + static +bye(argc, argv) + int argc; /* Number of arguments */ + char *argv[]; /* arguments */ +{ + extern int resettermname; + + if (connected) { + (void) shutdown(net, 2); + printf("Connection closed.\n"); + (void) NetClose(net); + connected = 0; + resettermname = 1; +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_connect(connected); +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ + /* reset options */ + tninit(); +#if defined(TN3270) + SetIn3270(); /* Get out of 3270 mode */ +#endif /* defined(TN3270) */ + } + if ((argc != 2) || (strcmp(argv[1], "fromquit") != 0)) { + longjmp(toplevel, 1); + /* NOTREACHED */ + } + return 1; /* Keep lint, etc., happy */ +} + +/*VARARGS*/ +quit() +{ + (void) call(bye, "bye", "fromquit", 0); + Exit(0); + /*NOTREACHED*/ +} + +/*VARARGS*/ + int +logout() +{ + send_do(TELOPT_LOGOUT, 1); + (void) netflush(); + return 1; +} + + +/* + * The SLC command. + */ + +struct slclist { + char *name; + char *help; + void (*handler)(); + int arg; +}; + +static void slc_help(); + +struct slclist SlcList[] = { + { "export", "Use local special character definitions", + slc_mode_export, 0 }, + { "import", "Use remote special character definitions", + slc_mode_import, 1 }, + { "check", "Verify remote special character definitions", + slc_mode_import, 0 }, + { "help", 0, slc_help, 0 }, + { "?", "Print help information", slc_help, 0 }, + { 0 }, +}; + + static void +slc_help() +{ + struct slclist *c; + + for (c = SlcList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\n", c->name, c->help); + else + printf("\n"); + } + } +} + + static struct slclist * +getslc(name) + char *name; +{ + return (struct slclist *) + genget(name, (char **) SlcList, sizeof(struct slclist)); +} + + static +slccmd(argc, argv) + int argc; + char *argv[]; +{ + struct slclist *c; + + if (argc != 2) { + fprintf(stderr, + "Need an argument to 'slc' command. 'slc ?' for help.\n"); + return 0; + } + c = getslc(argv[1]); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('slc ?' for help).\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('slc ?' for help).\n", + argv[1]); + return 0; + } + (*c->handler)(c->arg); + slcstate(); + return 1; +} + +/* + * The ENVIRON command. + */ + +struct envlist { + char *name; + char *help; + void (*handler)(); + int narg; +}; + +extern struct env_lst * + env_define P((unsigned char *, unsigned char *)); +extern void + env_undefine P((unsigned char *)), + env_export P((unsigned char *)), + env_unexport P((unsigned char *)), + env_send P((unsigned char *)), +#if defined(OLD_ENVIRON) && defined(ENV_HACK) + env_varval P((unsigned char *)), +#endif + env_list P((void)); +static void + env_help P((void)); + +struct envlist EnvList[] = { + { "define", "Define an environment variable", + (void (*)())env_define, 2 }, + { "undefine", "Undefine an environment variable", + env_undefine, 1 }, + { "export", "Mark an environment variable for automatic export", + env_export, 1 }, + { "unexport", "Don't mark an environment variable for automatic export", + env_unexport, 1 }, + { "send", "Send an environment variable", env_send, 1 }, + { "list", "List the current environment variables", + env_list, 0 }, +#if defined(OLD_ENVIRON) && defined(ENV_HACK) + { "varval", "Reverse VAR and VALUE (auto, right, wrong, status)", + env_varval, 1 }, +#endif + { "help", 0, env_help, 0 }, + { "?", "Print help information", env_help, 0 }, + { 0 }, +}; + + static void +env_help() +{ + struct envlist *c; + + for (c = EnvList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\n", c->name, c->help); + else + printf("\n"); + } + } +} + + static struct envlist * +getenvcmd(name) + char *name; +{ + return (struct envlist *) + genget(name, (char **) EnvList, sizeof(struct envlist)); +} + +env_cmd(argc, argv) + int argc; + char *argv[]; +{ + struct envlist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'environ' command. 'environ ?' for help.\n"); + return 0; + } + c = getenvcmd(argv[1]); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('environ ?' for help).\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('environ ?' for help).\n", + argv[1]); + return 0; + } + if (c->narg + 2 != argc) { + fprintf(stderr, + "Need %s%d argument%s to 'environ %s' command. 'environ ?' for help.\n", + c->narg < argc + 2 ? "only " : "", + c->narg, c->narg == 1 ? "" : "s", c->name); + return 0; + } + (*c->handler)(argv[2], argv[3]); + return 1; +} + +struct env_lst { + struct env_lst *next; /* pointer to next structure */ + struct env_lst *prev; /* pointer to previous structure */ + unsigned char *var; /* pointer to variable name */ + unsigned char *value; /* pointer to variable value */ + int export; /* 1 -> export with default list of variables */ + int welldefined; /* A well defined variable */ +}; + +struct env_lst envlisthead; + + struct env_lst * +env_find(var) + unsigned char *var; +{ + register struct env_lst *ep; + + for (ep = envlisthead.next; ep; ep = ep->next) { + if (strcmp((char *)ep->var, (char *)var) == 0) + return(ep); + } + return(NULL); +} + + void +env_init() +{ + extern char **environ; + register char **epp, *cp; + register struct env_lst *ep; + extern char *strchr(); + + for (epp = environ; *epp; epp++) { + if (cp = strchr(*epp, '=')) { + *cp = '\0'; + ep = env_define((unsigned char *)*epp, + (unsigned char *)cp+1); + ep->export = 0; + *cp = '='; + } + } + /* + * Special case for DISPLAY variable. If it is ":0.0" or + * "unix:0.0", we have to get rid of "unix" and insert our + * hostname. + */ + if ((ep = env_find("DISPLAY")) + && ((*ep->value == ':') + || (strncmp((char *)ep->value, "unix:", 5) == 0))) { + char hbuf[256+1]; + char *cp2 = strchr((char *)ep->value, ':'); + + gethostname(hbuf, 256); + hbuf[256] = '\0'; + cp = (char *)malloc(strlen(hbuf) + strlen(cp2) + 1); + sprintf((char *)cp, "%s%s", hbuf, cp2); + free(ep->value); + ep->value = (unsigned char *)cp; + } + /* + * If USER is not defined, but LOGNAME is, then add + * USER with the value from LOGNAME. By default, we + * don't export the USER variable. + */ + if ((env_find("USER") == NULL) && (ep = env_find("LOGNAME"))) { + env_define((unsigned char *)"USER", ep->value); + env_unexport((unsigned char *)"USER"); + } + env_export((unsigned char *)"DISPLAY"); + env_export((unsigned char *)"PRINTER"); +} + + struct env_lst * +env_define(var, value) + unsigned char *var, *value; +{ + register struct env_lst *ep; + + if (ep = env_find(var)) { + if (ep->var) + free(ep->var); + if (ep->value) + free(ep->value); + } else { + ep = (struct env_lst *)malloc(sizeof(struct env_lst)); + ep->next = envlisthead.next; + envlisthead.next = ep; + ep->prev = &envlisthead; + if (ep->next) + ep->next->prev = ep; + } + ep->welldefined = opt_welldefined(var); + ep->export = 1; + ep->var = (unsigned char *)strdup((char *)var); + ep->value = (unsigned char *)strdup((char *)value); + return(ep); +} + + void +env_undefine(var) + unsigned char *var; +{ + register struct env_lst *ep; + + if (ep = env_find(var)) { + ep->prev->next = ep->next; + if (ep->next) + ep->next->prev = ep->prev; + if (ep->var) + free(ep->var); + if (ep->value) + free(ep->value); + free(ep); + } +} + + void +env_export(var) + unsigned char *var; +{ + register struct env_lst *ep; + + if (ep = env_find(var)) + ep->export = 1; +} + + void +env_unexport(var) + unsigned char *var; +{ + register struct env_lst *ep; + + if (ep = env_find(var)) + ep->export = 0; +} + + void +env_send(var) + unsigned char *var; +{ + register struct env_lst *ep; + + if (my_state_is_wont(TELOPT_NEW_ENVIRON) +#ifdef OLD_ENVIRON + && my_state_is_wont(TELOPT_OLD_ENVIRON) +#endif + ) { + fprintf(stderr, + "Cannot send '%s': Telnet ENVIRON option not enabled\n", + var); + return; + } + ep = env_find(var); + if (ep == 0) { + fprintf(stderr, "Cannot send '%s': variable not defined\n", + var); + return; + } + env_opt_start_info(); + env_opt_add(ep->var); + env_opt_end(0); +} + + void +env_list() +{ + register struct env_lst *ep; + + for (ep = envlisthead.next; ep; ep = ep->next) { + printf("%c %-20s %s\n", ep->export ? '*' : ' ', + ep->var, ep->value); + } +} + + unsigned char * +env_default(init, welldefined) + int init; +{ + static struct env_lst *nep = NULL; + + if (init) { + nep = &envlisthead; + return; + } + if (nep) { + while (nep = nep->next) { + if (nep->export && (nep->welldefined == welldefined)) + return(nep->var); + } + } + return(NULL); +} + + unsigned char * +env_getvalue(var) + unsigned char *var; +{ + register struct env_lst *ep; + + if (ep = env_find(var)) + return(ep->value); + return(NULL); +} + +#if defined(OLD_ENVIRON) && defined(ENV_HACK) + void +env_varval(what) + unsigned char *what; +{ + extern int old_env_var, old_env_value, env_auto; + int len = strlen((char *)what); + + if (len == 0) + goto unknown; + + if (strncasecmp((char *)what, "status", len) == 0) { + if (env_auto) + printf("%s%s", "VAR and VALUE are/will be ", + "determined automatically\n"); + if (old_env_var == OLD_ENV_VAR) + printf("VAR and VALUE set to correct definitions\n"); + else + printf("VAR and VALUE definitions are reversed\n"); + } else if (strncasecmp((char *)what, "auto", len) == 0) { + env_auto = 1; + old_env_var = OLD_ENV_VALUE; + old_env_value = OLD_ENV_VAR; + } else if (strncasecmp((char *)what, "right", len) == 0) { + env_auto = 0; + old_env_var = OLD_ENV_VAR; + old_env_value = OLD_ENV_VALUE; + } else if (strncasecmp((char *)what, "wrong", len) == 0) { + env_auto = 0; + old_env_var = OLD_ENV_VALUE; + old_env_value = OLD_ENV_VAR; + } else { +unknown: + printf("Unknown \"varval\" command. (\"auto\", \"right\", \"wrong\", \"status\")\n"); + } +} +#endif + +#if defined(AUTHENTICATION) +/* + * The AUTHENTICATE command. + */ + +struct authlist { + char *name; + char *help; + int (*handler)(); + int narg; +}; + +extern int + auth_enable P((char *)), + auth_disable P((char *)), + auth_status P((void)); +static int + auth_help P((void)); + +struct authlist AuthList[] = { + { "status", "Display current status of authentication information", + auth_status, 0 }, + { "disable", "Disable an authentication type ('auth disable ?' for more)", + auth_disable, 1 }, + { "enable", "Enable an authentication type ('auth enable ?' for more)", + auth_enable, 1 }, + { "help", 0, auth_help, 0 }, + { "?", "Print help information", auth_help, 0 }, + { 0 }, +}; + + static int +auth_help() +{ + struct authlist *c; + + for (c = AuthList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\n", c->name, c->help); + else + printf("\n"); + } + } + return 0; +} + +auth_cmd(argc, argv) + int argc; + char *argv[]; +{ + struct authlist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'auth' command. 'auth ?' for help.\n"); + return 0; + } + + c = (struct authlist *) + genget(argv[1], (char **) AuthList, sizeof(struct authlist)); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('auth ?' for help).\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('auth ?' for help).\n", + argv[1]); + return 0; + } + if (c->narg + 2 != argc) { + fprintf(stderr, + "Need %s%d argument%s to 'auth %s' command. 'auth ?' for help.\n", + c->narg < argc + 2 ? "only " : "", + c->narg, c->narg == 1 ? "" : "s", c->name); + return 0; + } + return((*c->handler)(argv[2], argv[3])); +} +#endif + +#ifdef ENCRYPTION +/* + * The ENCRYPT command. + */ + +struct encryptlist { + char *name; + char *help; + int (*handler)(); + int needconnect; + int minarg; + int maxarg; +}; + +extern int + EncryptEnable P((char *, char *)), + EncryptDisable P((char *, char *)), + EncryptType P((char *, char *)), + EncryptStart P((char *)), + EncryptStartInput P((void)), + EncryptStartOutput P((void)), + EncryptStop P((char *)), + EncryptStopInput P((void)), + EncryptStopOutput P((void)), + EncryptStatus P((void)); +static int + EncryptHelp P((void)); + +struct encryptlist EncryptList[] = { + { "enable", "Enable encryption. ('encrypt enable ?' for more)", + EncryptEnable, 1, 1, 2 }, + { "disable", "Disable encryption. ('encrypt enable ?' for more)", + EncryptDisable, 0, 1, 2 }, + { "type", "Set encryption type. ('encrypt type ?' for more)", + EncryptType, 0, 1, 1 }, + { "start", "Start encryption. ('encrypt start ?' for more)", + EncryptStart, 1, 0, 1 }, + { "stop", "Stop encryption. ('encrypt stop ?' for more)", + EncryptStop, 1, 0, 1 }, + { "input", "Start encrypting the input stream", + EncryptStartInput, 1, 0, 0 }, + { "-input", "Stop encrypting the input stream", + EncryptStopInput, 1, 0, 0 }, + { "output", "Start encrypting the output stream", + EncryptStartOutput, 1, 0, 0 }, + { "-output", "Stop encrypting the output stream", + EncryptStopOutput, 1, 0, 0 }, + + { "status", "Display current status of authentication information", + EncryptStatus, 0, 0, 0 }, + { "help", 0, EncryptHelp, 0, 0, 0 }, + { "?", "Print help information", EncryptHelp, 0, 0, 0 }, + { 0 }, +}; + + static int +EncryptHelp() +{ + struct encryptlist *c; + + for (c = EncryptList; c->name; c++) { + if (c->help) { + if (*c->help) + printf("%-15s %s\n", c->name, c->help); + else + printf("\n"); + } + } + return 0; +} + +encrypt_cmd(argc, argv) + int argc; + char *argv[]; +{ + struct encryptlist *c; + + if (argc < 2) { + fprintf(stderr, + "Need an argument to 'encrypt' command. 'encrypt ?' for help.\n"); + return 0; + } + + c = (struct encryptlist *) + genget(argv[1], (char **) EncryptList, sizeof(struct encryptlist)); + if (c == 0) { + fprintf(stderr, "'%s': unknown argument ('encrypt ?' for help).\n", + argv[1]); + return 0; + } + if (Ambiguous(c)) { + fprintf(stderr, "'%s': ambiguous argument ('encrypt ?' for help).\n", + argv[1]); + return 0; + } + argc -= 2; + if (argc < c->minarg || argc > c->maxarg) { + if (c->minarg == c->maxarg) { + fprintf(stderr, "Need %s%d argument%s ", + c->minarg < argc ? "only " : "", c->minarg, + c->minarg == 1 ? "" : "s"); + } else { + fprintf(stderr, "Need %s%d-%d arguments ", + c->maxarg < argc ? "only " : "", c->minarg, c->maxarg); + } + fprintf(stderr, "to 'encrypt %s' command. 'encrypt ?' for help.\n", + c->name); + return 0; + } + if (c->needconnect && !connected) { + if (!(argc && (isprefix(argv[2], "help") || isprefix(argv[2], "?")))) { + printf("?Need to be connected first.\n"); + return 0; + } + } + return ((*c->handler)(argc > 0 ? argv[2] : 0, + argc > 1 ? argv[3] : 0, + argc > 2 ? argv[4] : 0)); +} +#endif /* ENCRYPTION */ + +#if (defined(unix) || defined(__APPLE__)) && defined(TN3270) + static void +filestuff(fd) + int fd; +{ + int res; + +#ifdef F_GETOWN + setconnmode(0); + res = fcntl(fd, F_GETOWN, 0); + setcommandmode(); + + if (res == -1) { + perror("fcntl"); + return; + } + printf("\tOwner is %d.\n", res); +#endif + + setconnmode(0); + res = fcntl(fd, F_GETFL, 0); + setcommandmode(); + + if (res == -1) { + perror("fcntl"); + return; + } +#ifdef notdef + printf("\tFlags are 0x%x: %s\n", res, decodeflags(res)); +#endif +} +#endif /* (defined(unix) || defined(__APPLE__)) && defined(TN3270) */ + +/* + * Print status about the connection. + */ + /*ARGSUSED*/ + static +status(argc, argv) + int argc; + char *argv[]; +{ + if (connected) { + printf("Connected to %s.\n", hostname); + if ((argc < 2) || strcmp(argv[1], "notmuch")) { + int mode = getconnmode(); + + if (my_want_state_is_will(TELOPT_LINEMODE)) { + printf("Operating with LINEMODE option\n"); + printf("%s line editing\n", (mode&MODE_EDIT) ? "Local" : "No"); + printf("%s catching of signals\n", + (mode&MODE_TRAPSIG) ? "Local" : "No"); + slcstate(); +#ifdef KLUDGELINEMODE + } else if (kludgelinemode && my_want_state_is_dont(TELOPT_SGA)) { + printf("Operating in obsolete linemode\n"); +#endif + } else { + printf("Operating in single character mode\n"); + if (localchars) + printf("Catching signals locally\n"); + } + printf("%s character echo\n", (mode&MODE_ECHO) ? "Local" : "Remote"); + if (my_want_state_is_will(TELOPT_LFLOW)) + printf("%s flow control\n", (mode&MODE_FLOW) ? "Local" : "No"); +#ifdef ENCRYPTION + encrypt_display(); +#endif /* ENCRYPTION */ + } + } else { + printf("No connection.\n"); + } +# if !defined(TN3270) + printf("Escape character is '%s'.\n", control(escape)); + (void) fflush(stdout); +# else /* !defined(TN3270) */ + if ((!In3270) && ((argc < 2) || strcmp(argv[1], "notmuch"))) { + printf("Escape character is '%s'.\n", control(escape)); + } +# if defined(unix) || defined(__APPLE__) + if ((argc >= 2) && !strcmp(argv[1], "everything")) { + printf("SIGIO received %d time%s.\n", + sigiocount, (sigiocount == 1)? "":"s"); + if (In3270) { + printf("Process ID %d, process group %d.\n", + getpid(), getpgrp(getpid())); + printf("Terminal input:\n"); + filestuff(tin); + printf("Terminal output:\n"); + filestuff(tout); + printf("Network socket:\n"); + filestuff(net); + } + } + if (In3270 && transcom) { + printf("Transparent mode command is '%s'.\n", transcom); + } +# endif /* defined(unix) || defined(__APPLE__) */ + (void) fflush(stdout); + if (In3270) { + return 0; + } +# endif /* defined(TN3270) */ + return 1; +} + +#ifdef SIGINFO +/* + * Function that gets called when SIGINFO is received. + */ +ayt_status() +{ + (void) call(status, "status", "notmuch", 0); +} +#endif + +unsigned long inet_addr(); + + int +tn(argc, argv) + int argc; + char *argv[]; +{ + register struct hostent *host = 0; + struct sockaddr_in sin; + struct servent *sp = 0; + unsigned long temp; + extern char *inet_ntoa(); +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + char *srp = 0, *strrchr(); + unsigned long sourceroute(), srlen; +#endif + char *cmd, *hostp = 0, *portp = 0, *user = 0; + + /* clear the socket address prior to use */ + memset((char *)&sin, 0, sizeof(sin)); + + if (connected) { + printf("?Already connected to %s\n", hostname); + setuid(getuid()); + return 0; + } + if (argc < 2) { + (void) strcpy(line, "open "); + printf("(to) "); + (void) fgets(&line[strlen(line)], sizeof(line) - strlen(line), stdin); + makeargv(); + argc = margc; + argv = margv; + } + cmd = *argv; + --argc; ++argv; + while (argc) { + if (strcmp(*argv, "help") == 0 || isprefix(*argv, "?")) + goto usage; + if (strcmp(*argv, "-l") == 0) { + --argc; ++argv; + if (argc == 0) + goto usage; + user = *argv++; + --argc; + continue; + } + if (strcmp(*argv, "-a") == 0) { + --argc; ++argv; + autologin = 1; + continue; + } + if (hostp == 0) { + hostp = *argv++; + --argc; + continue; + } + if (portp == 0) { + portp = *argv++; + --argc; + continue; + } + usage: + printf("usage: %s [-l user] [-a] host-name [port]\n", cmd); + setuid(getuid()); + return 0; + } + if (hostp == 0) + goto usage; + +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + if (hostp[0] == '@' || hostp[0] == '!') { + if ((hostname = strrchr(hostp, ':')) == NULL) + hostname = strrchr(hostp, '@'); + hostname++; + srp = 0; + temp = sourceroute(hostp, &srp, &srlen); + if (temp == 0) { + herror(srp); + setuid(getuid()); + return 0; + } else if (temp == -1) { + printf("Bad source route option: %s\n", hostp); + setuid(getuid()); + return 0; + } else { + sin.sin_addr.s_addr = temp; + sin.sin_family = AF_INET; + } + } else { +#endif + temp = inet_addr(hostp); + if (temp != (unsigned long) -1) { + sin.sin_addr.s_addr = temp; + sin.sin_family = AF_INET; + (void) strcpy(_hostname, hostp); + hostname = _hostname; + } else { + host = gethostbyname(hostp); + if (host) { + sin.sin_family = host->h_addrtype; +#if defined(h_addr) /* In 4.3, this is a #define */ + memmove((caddr_t)&sin.sin_addr, + host->h_addr_list[0], host->h_length); +#else /* defined(h_addr) */ + memmove((caddr_t)&sin.sin_addr, host->h_addr, host->h_length); +#endif /* defined(h_addr) */ + strncpy(_hostname, host->h_name, sizeof(_hostname)); + _hostname[sizeof(_hostname)-1] = '\0'; + hostname = _hostname; + } else { + herror(hostp); + setuid(getuid()); + return 0; + } + } +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + } +#endif + if (portp) { + if (*portp == '-') { + portp++; + telnetport = 1; + } else + telnetport = 0; + sin.sin_port = atoi(portp); + if (sin.sin_port == 0) { + sp = getservbyname(portp, "tcp"); + if (sp) + sin.sin_port = sp->s_port; + else { + printf("%s: bad port number\n", portp); + setuid(getuid()); + return 0; + } + } else { +#if !defined(htons) + u_short htons P((unsigned short)); +#endif /* !defined(htons) */ + sin.sin_port = htons(sin.sin_port); + } + } else { + if (sp == 0) { + sp = getservbyname("telnet", "tcp"); + if (sp == 0) { + fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); + setuid(getuid()); + return 0; + } + sin.sin_port = sp->s_port; + } + telnetport = 1; + } + printf("Trying %s...\n", inet_ntoa(sin.sin_addr)); + do { + net = socket(AF_INET, SOCK_STREAM, 0); + setuid(getuid()); + if (net < 0) { + perror("telnet: socket"); + return 0; + } +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0) + perror("setsockopt (IP_OPTIONS)"); +#endif +#if defined(IPPROTO_IP) && defined(IP_TOS) + { +# if defined(HAS_GETTOS) + struct tosent *tp; + if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) + tos = tp->t_tos; +# endif + if (tos < 0) + tos = 020; /* Low Delay bit */ + if (tos + && (setsockopt(net, IPPROTO_IP, IP_TOS, + (char *)&tos, sizeof(int)) < 0) + && (errno != ENOPROTOOPT)) + perror("telnet: setsockopt (IP_TOS) (ignored)"); + } +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + + if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) { + perror("setsockopt (SO_DEBUG)"); + } + + if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) { +#if defined(h_addr) /* In 4.3, this is a #define */ + if (host && host->h_addr_list[1]) { + int oerrno = errno; + + fprintf(stderr, "telnet: connect to address %s: ", + inet_ntoa(sin.sin_addr)); + errno = oerrno; + perror((char *)0); + host->h_addr_list++; + memmove((caddr_t)&sin.sin_addr, + host->h_addr_list[0], host->h_length); + (void) NetClose(net); + continue; + } +#endif /* defined(h_addr) */ + perror("telnet: Unable to connect to remote host"); + return 0; + } + connected++; +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_connect(connected); +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ + } while (connected == 0); + cmdrc(hostp, hostname); + if (autologin && user == NULL) { + struct passwd *pw; + + user = getenv("USER"); + if (user == NULL || + (pw = getpwnam(user)) && pw->pw_uid != getuid()) { + if (pw = getpwuid(getuid())) + user = pw->pw_name; + else + user = NULL; + } + } + if (user) { + env_define((unsigned char *)"USER", (unsigned char *)user); + env_export((unsigned char *)"USER"); + } + (void) call(status, "status", "notmuch", 0); + if (setjmp(peerdied) == 0) + telnet(user); + (void) NetClose(net); + ExitString("Connection closed by foreign host.\n",1); + /*NOTREACHED*/ +} + +#define HELPINDENT (sizeof ("connect")) + +static char + openhelp[] = "connect to a site", + closehelp[] = "close current connection", + logouthelp[] = "forcibly logout remote user and close the connection", + quithelp[] = "exit telnet", + statushelp[] = "print status information", + helphelp[] = "print help information", + sendhelp[] = "transmit special characters ('send ?' for more)", + sethelp[] = "set operating parameters ('set ?' for more)", + unsethelp[] = "unset operating parameters ('unset ?' for more)", + togglestring[] ="toggle operating parameters ('toggle ?' for more)", + slchelp[] = "change state of special charaters ('slc ?' for more)", + displayhelp[] = "display operating parameters", +#if defined(TN3270) && (defined(unix) || defined(__APPLE__)) + transcomhelp[] = "specify Unix command for transparent mode pipe", +#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */ +#if defined(AUTHENTICATION) + authhelp[] = "turn on (off) authentication ('auth ?' for more)", +#endif +#ifdef ENCRYPTION + encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)", +#endif /* ENCRYPTION */ +#if defined(unix) || defined(__APPLE__) + zhelp[] = "suspend telnet", +#endif /* defined(unix) || defined(__APPLE__) */ + shellhelp[] = "invoke a subshell", + envhelp[] = "change environment variables ('environ ?' for more)", + modestring[] = "try to enter line or character mode ('mode ?' for more)"; + +static int help(); + +static Command cmdtab[] = { + { "close", closehelp, bye, 1 }, + { "logout", logouthelp, logout, 1 }, + { "display", displayhelp, display, 0 }, + { "mode", modestring, modecmd, 0 }, + { "open", openhelp, tn, 0 }, + { "quit", quithelp, quit, 0 }, + { "send", sendhelp, sendcmd, 0 }, + { "set", sethelp, setcmd, 0 }, + { "unset", unsethelp, unsetcmd, 0 }, + { "status", statushelp, status, 0 }, + { "toggle", togglestring, toggle, 0 }, + { "slc", slchelp, slccmd, 0 }, +#if defined(TN3270) && (defined(unix) || defined(__APPLE__)) + { "transcom", transcomhelp, settranscom, 0 }, +#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */ +#if defined(AUTHENTICATION) + { "auth", authhelp, auth_cmd, 0 }, +#endif +#ifdef ENCRYPTION + { "encrypt", encrypthelp, encrypt_cmd, 0 }, +#endif /* ENCRYPTION */ +#if defined(unix) || defined(__APPLE__) + { "z", zhelp, suspend, 0 }, +#endif /* defined(unix) || defined(__APPLE__) */ +#if defined(TN3270) + { "!", shellhelp, shell, 1 }, +#else + { "!", shellhelp, shell, 0 }, +#endif + { "environ", envhelp, env_cmd, 0 }, + { "?", helphelp, help, 0 }, + { 0 } +}; + +static char crmodhelp[] = "deprecated command -- use 'toggle crmod' instead"; +static char escapehelp[] = "deprecated command -- use 'set escape' instead"; + +static Command cmdtab2[] = { + { "help", 0, help, 0 }, + { "escape", escapehelp, setescape, 0 }, + { "crmod", crmodhelp, togcrmod, 0 }, + { 0 } +}; + + +/* + * Call routine with argc, argv set from args (terminated by 0). + */ + +#if __STDC__ +#include +#else +#include +#endif + + + /*VARARGS1*/ + static +#if __STDC__ +call(intrtn_t routine, ...) +{ +#else +call(va_alist) + va_dcl +{ + intrtn_t routine; +#endif + va_list ap; + char *args[100]; + int argno = 0; + +#if __STDC__ + va_start(ap, routine); +#else + va_start(ap); + routine = (va_arg(ap, intrtn_t)); +#endif + while ((args[argno++] = va_arg(ap, char *)) != 0) { + ; + } + va_end(ap); + return (*routine)(argno-1, args); +} + + + static Command * +getcmd(name) + char *name; +{ + Command *cm; + + if (cm = (Command *) genget(name, (char **) cmdtab, sizeof(Command))) + return cm; + return (Command *) genget(name, (char **) cmdtab2, sizeof(Command)); +} + + void +command(top, tbuf, cnt) + int top; + char *tbuf; + int cnt; +{ + register Command *c; + + setcommandmode(); + if (!top) { + putchar('\n'); +#if defined(unix) || defined(__APPLE__) + } else { + (void) signal(SIGINT, SIG_DFL); + (void) signal(SIGQUIT, SIG_DFL); +#endif /* defined(unix) || defined(__APPLE__) */ + } + for (;;) { + if (rlogin == _POSIX_VDISABLE) + printf("%s> ", prompt); + if (tbuf) { + register char *cp; + cp = line; + while (cnt > 0 && (*cp++ = *tbuf++) != '\n') + cnt--; + tbuf = 0; + if (cp == line || *--cp != '\n' || cp == line) + goto getline; + *cp = '\0'; + if (rlogin == _POSIX_VDISABLE) + printf("%s\n", line); + } else { + getline: + if (rlogin != _POSIX_VDISABLE) + printf("%s> ", prompt); + if (fgets(line, sizeof(line), stdin) == NULL) { + if (feof(stdin) || ferror(stdin)) { + (void) quit(); + /*NOTREACHED*/ + } + break; + } + } + if (line[0] == 0) + break; + makeargv(); + if (margv[0] == 0) { + break; + } + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->needconnect && !connected) { + printf("?Need to be connected first.\n"); + continue; + } + if ((*c->handler)(margc, margv)) { + break; + } + } + if (!top) { + if (!connected) { + longjmp(toplevel, 1); + /*NOTREACHED*/ + } +#if defined(TN3270) + if (shell_active == 0) { + setconnmode(0); + } +#else /* defined(TN3270) */ + setconnmode(0); +#endif /* defined(TN3270) */ + } +} + +/* + * Help command. + */ + static +help(argc, argv) + int argc; + char *argv[]; +{ + register Command *c; + + if (argc == 1) { + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c->name; c++) + if (c->help) { + printf("%-*s\t%s\n", HELPINDENT, c->name, + c->help); + } + return 0; + } + while (--argc > 0) { + register char *arg; + arg = *++argv; + c = getcmd(arg); + if (Ambiguous(c)) + printf("?Ambiguous help command %s\n", arg); + else if (c == (Command *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%s\n", c->help); + } + return 0; +} + +static char *rcname = 0; +static char rcbuf[128]; + +cmdrc(m1, m2) + char *m1, *m2; +{ + register Command *c; + FILE *rcfile; + int gotmachine = 0; + int l1 = strlen(m1); + int l2 = strlen(m2); + char m1save[64]; + + if (skiprc) + return; + + strcpy(m1save, m1); + m1 = m1save; + + if (rcname == 0) { + rcname = getenv("HOME"); + if (rcname) + strcpy(rcbuf, rcname); + else + rcbuf[0] = '\0'; + strcat(rcbuf, "/.telnetrc"); + rcname = rcbuf; + } + + if ((rcfile = fopen(rcname, "r")) == 0) { + return; + } + + for (;;) { + if (fgets(line, sizeof(line), rcfile) == NULL) + break; + if (line[0] == 0) + break; + if (line[0] == '#') + continue; + if (gotmachine) { + if (!isspace(line[0])) + gotmachine = 0; + } + if (gotmachine == 0) { + if (isspace(line[0])) + continue; + if (strncasecmp(line, m1, l1) == 0) + strncpy(line, &line[l1], sizeof(line) - l1); + else if (strncasecmp(line, m2, l2) == 0) + strncpy(line, &line[l2], sizeof(line) - l2); + else if (strncasecmp(line, "DEFAULT", 7) == 0) + strncpy(line, &line[7], sizeof(line) - 7); + else + continue; + if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n') + continue; + gotmachine = 1; + } + makeargv(); + if (margv[0] == 0) + continue; + c = getcmd(margv[0]); + if (Ambiguous(c)) { + printf("?Ambiguous command: %s\n", margv[0]); + continue; + } + if (c == 0) { + printf("?Invalid command: %s\n", margv[0]); + continue; + } + /* + * This should never happen... + */ + if (c->needconnect && !connected) { + printf("?Need to be connected first for %s.\n", margv[0]); + continue; + } + (*c->handler)(margc, margv); + } + fclose(rcfile); +} + +#if defined(IP_OPTIONS) && defined(IPPROTO_IP) + +/* + * Source route is handed in as + * [!]@hop1@hop2...[@|:]dst + * If the leading ! is present, it is a + * strict source route, otherwise it is + * assmed to be a loose source route. + * + * We fill in the source route option as + * hop1,hop2,hop3...dest + * and return a pointer to hop1, which will + * be the address to connect() to. + * + * Arguments: + * arg: pointer to route list to decipher + * + * cpp: If *cpp is not equal to NULL, this is a + * pointer to a pointer to a character array + * that should be filled in with the option. + * + * lenp: pointer to an integer that contains the + * length of *cpp if *cpp != NULL. + * + * Return values: + * + * Returns the address of the host to connect to. If the + * return value is -1, there was a syntax error in the + * option, either unknown characters, or too many hosts. + * If the return value is 0, one of the hostnames in the + * path is unknown, and *cpp is set to point to the bad + * hostname. + * + * *cpp: If *cpp was equal to NULL, it will be filled + * in with a pointer to our static area that has + * the option filled in. This will be 32bit aligned. + * + * *lenp: This will be filled in with how long the option + * pointed to by *cpp is. + * + */ + unsigned long +sourceroute(arg, cpp, lenp) + char *arg; + char **cpp; + int *lenp; +{ + static char lsr[44]; +#ifdef sysV88 + static IOPTN ipopt; +#endif + char *cp, *cp2, *lsrp, *lsrep; + register int tmp; + struct in_addr sin_addr; + register struct hostent *host = 0; + register char c; + + /* + * Verify the arguments, and make sure we have + * at least 7 bytes for the option. + */ + if (cpp == NULL || lenp == NULL) + return((unsigned long)-1); + if (*cpp != NULL && *lenp < 7) + return((unsigned long)-1); + /* + * Decide whether we have a buffer passed to us, + * or if we need to use our own static buffer. + */ + if (*cpp) { + lsrp = *cpp; + lsrep = lsrp + *lenp; + } else { + *cpp = lsrp = lsr; + lsrep = lsrp + 44; + } + + cp = arg; + + /* + * Next, decide whether we have a loose source + * route or a strict source route, and fill in + * the begining of the option. + */ +#ifndef sysV88 + if (*cp == '!') { + cp++; + *lsrp++ = IPOPT_SSRR; + } else + *lsrp++ = IPOPT_LSRR; +#else + if (*cp == '!') { + cp++; + ipopt.io_type = IPOPT_SSRR; + } else + ipopt.io_type = IPOPT_LSRR; +#endif + + if (*cp != '@') + return((unsigned long)-1); + +#ifndef sysV88 + lsrp++; /* skip over length, we'll fill it in later */ + *lsrp++ = 4; +#endif + + cp++; + + sin_addr.s_addr = 0; + + for (c = 0;;) { + if (c == ':') + cp2 = 0; + else for (cp2 = cp; c = *cp2; cp2++) { + if (c == ',') { + *cp2++ = '\0'; + if (*cp2 == '@') + cp2++; + } else if (c == '@') { + *cp2++ = '\0'; + } else if (c == ':') { + *cp2++ = '\0'; + } else + continue; + break; + } + if (!c) + cp2 = 0; + + if ((tmp = inet_addr(cp)) != -1) { + sin_addr.s_addr = tmp; + } else if (host = gethostbyname(cp)) { +#if defined(h_addr) + memmove((caddr_t)&sin_addr, + host->h_addr_list[0], host->h_length); +#else + memmove((caddr_t)&sin_addr, host->h_addr, host->h_length); +#endif + } else { + *cpp = cp; + return(0); + } + memmove(lsrp, (char *)&sin_addr, 4); + lsrp += 4; + if (cp2) + cp = cp2; + else + break; + /* + * Check to make sure there is space for next address + */ + if (lsrp + 4 > lsrep) + return((unsigned long)-1); + } +#ifndef sysV88 + if ((*(*cpp+IPOPT_OLEN) = lsrp - *cpp) <= 7) { + *cpp = 0; + *lenp = 0; + return((unsigned long)-1); + } + *lsrp++ = IPOPT_NOP; /* 32 bit word align it */ + *lenp = lsrp - *cpp; +#else + ipopt.io_len = lsrp - *cpp; + if (ipopt.io_len <= 5) { /* Is 3 better ? */ + *cpp = 0; + *lenp = 0; + return((unsigned long)-1); + } + *lenp = sizeof(ipopt); + *cpp = (char *) &ipopt; +#endif + return(sin_addr.s_addr); +} +#endif diff --git a/telnet.tproj/defines.h b/telnet.tproj/defines.h new file mode 100644 index 0000000..51a9283 --- /dev/null +++ b/telnet.tproj/defines.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defines.h 8.1 (Berkeley) 6/6/93 + */ + +#define settimer(x) clocks.x = clocks.system++ + +#if !defined(TN3270) + +#define SetIn3270() + +#endif /* !defined(TN3270) */ + +#define NETADD(c) { *netoring.supply = c; ring_supplied(&netoring, 1); } +#define NET2ADD(c1,c2) { NETADD(c1); NETADD(c2); } +#define NETBYTES() (ring_full_count(&netoring)) +#define NETROOM() (ring_empty_count(&netoring)) + +#define TTYADD(c) if (!(SYNCHing||flushout)) { \ + *ttyoring.supply = c; \ + ring_supplied(&ttyoring, 1); \ + } +#define TTYBYTES() (ring_full_count(&ttyoring)) +#define TTYROOM() (ring_empty_count(&ttyoring)) + +/* Various modes */ +#define MODE_LOCAL_CHARS(m) ((m)&(MODE_EDIT|MODE_TRAPSIG)) +#define MODE_LOCAL_ECHO(m) ((m)&MODE_ECHO) +#define MODE_COMMAND_LINE(m) ((m)==-1) + +#define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */ diff --git a/telnet.tproj/externs.h b/telnet.tproj/externs.h new file mode 100644 index 0000000..006efac --- /dev/null +++ b/telnet.tproj/externs.h @@ -0,0 +1,505 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)externs.h 8.3 (Berkeley) 5/30/95 + */ + +#ifndef BSD +# define BSD 43 +#endif + +/* + * ucb stdio.h defines BSD as something wierd + */ +#if defined(sun) && defined(__svr4__) +#define BSD 43 +#endif + +#ifndef USE_TERMIO +# if BSD > 43 || defined(SYSV_TERMIO) +# define USE_TERMIO +# endif +#endif + +#include +#include +#if defined(CRAY) && !defined(NO_BSD_SETJMP) +#include +#endif +#ifndef FILIO_H +#include +#else +#include +#endif +#ifdef CRAY +# include +#endif /* CRAY */ +#ifdef USE_TERMIO +# ifndef VINTR +# ifdef SYSV_TERMIO +# include +# else +# include +# define termio termios +# endif +# endif +#endif +#if defined(NO_CC_T) || !defined(USE_TERMIO) +# if !defined(USE_TERMIO) +typedef char cc_t; +# else +typedef unsigned char cc_t; +# endif +#endif + +#ifndef NO_STRING_H +#include +#else +#include +#endif + +#ifndef _POSIX_VDISABLE +# ifdef sun +# include /* pick up VDISABLE definition, mayby */ +# endif +# ifdef VDISABLE +# define _POSIX_VDISABLE VDISABLE +# else +# define _POSIX_VDISABLE ((cc_t)'\377') +# endif +#endif + +#define SUBBUFSIZE 256 + +#ifndef CRAY +extern int errno; /* outside this world */ +#endif /* !CRAY */ + +#if !defined(P) +# ifdef __STDC__ +# define P(x) x +# else +# define P(x) () +# endif +#endif + +extern int + autologin, /* Autologin enabled */ + skiprc, /* Don't process the ~/.telnetrc file */ + eight, /* use eight bit mode (binary in and/or out */ + flushout, /* flush output */ + connected, /* Are we connected to the other side? */ + globalmode, /* Mode tty should be in */ + In3270, /* Are we in 3270 mode? */ + telnetport, /* Are we connected to the telnet port? */ + localflow, /* Flow control handled locally */ + restartany, /* If flow control, restart output on any character */ + localchars, /* we recognize interrupt/quit */ + donelclchars, /* the user has set "localchars" */ + showoptions, + net, /* Network file descriptor */ + tin, /* Terminal input file descriptor */ + tout, /* Terminal output file descriptor */ + crlf, /* Should '\r' be mapped to (or )? */ + autoflush, /* flush output when interrupting? */ + autosynch, /* send interrupt characters with SYNCH? */ + SYNCHing, /* Is the stream in telnet SYNCH mode? */ + donebinarytoggle, /* the user has put us in binary */ + dontlecho, /* do we suppress local echoing right now? */ + crmod, + netdata, /* Print out network data flow */ + prettydump, /* Print "netdata" output in user readable format */ +#if defined(unix) || defined(__APPLE__) +#if defined(TN3270) + cursesdata, /* Print out curses data flow */ + apitrace, /* Trace API transactions */ +#endif /* defined(TN3270) */ + termdata, /* Print out terminal data flow */ +#endif /* defined(unix) || defined(__APPLE__) */ + debug; /* Debug level */ + +extern cc_t escape; /* Escape to command mode */ +extern cc_t rlogin; /* Rlogin mode escape character */ +#ifdef KLUDGELINEMODE +extern cc_t echoc; /* Toggle local echoing */ +#endif + +extern char + *prompt; /* Prompt for command. */ + +extern char + doopt[], + dont[], + will[], + wont[], + options[], /* All the little options */ + *hostname; /* Who are we connected to? */ +#ifdef ENCRYPTION +extern void (*encrypt_output) P((unsigned char *, int)); +extern int (*decrypt_input) P((int)); +#endif /* ENCRYPTION */ + +/* + * We keep track of each side of the option negotiation. + */ + +#define MY_STATE_WILL 0x01 +#define MY_WANT_STATE_WILL 0x02 +#define MY_STATE_DO 0x04 +#define MY_WANT_STATE_DO 0x08 + +/* + * Macros to check the current state of things + */ + +#define my_state_is_do(opt) (options[opt]&MY_STATE_DO) +#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) +#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) +#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) + +#define my_state_is_dont(opt) (!my_state_is_do(opt)) +#define my_state_is_wont(opt) (!my_state_is_will(opt)) +#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) +#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) + +#define set_my_state_do(opt) {options[opt] |= MY_STATE_DO;} +#define set_my_state_will(opt) {options[opt] |= MY_STATE_WILL;} +#define set_my_want_state_do(opt) {options[opt] |= MY_WANT_STATE_DO;} +#define set_my_want_state_will(opt) {options[opt] |= MY_WANT_STATE_WILL;} + +#define set_my_state_dont(opt) {options[opt] &= ~MY_STATE_DO;} +#define set_my_state_wont(opt) {options[opt] &= ~MY_STATE_WILL;} +#define set_my_want_state_dont(opt) {options[opt] &= ~MY_WANT_STATE_DO;} +#define set_my_want_state_wont(opt) {options[opt] &= ~MY_WANT_STATE_WILL;} + +/* + * Make everything symetrical + */ + +#define HIS_STATE_WILL MY_STATE_DO +#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO +#define HIS_STATE_DO MY_STATE_WILL +#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL + +#define his_state_is_do my_state_is_will +#define his_state_is_will my_state_is_do +#define his_want_state_is_do my_want_state_is_will +#define his_want_state_is_will my_want_state_is_do + +#define his_state_is_dont my_state_is_wont +#define his_state_is_wont my_state_is_dont +#define his_want_state_is_dont my_want_state_is_wont +#define his_want_state_is_wont my_want_state_is_dont + +#define set_his_state_do set_my_state_will +#define set_his_state_will set_my_state_do +#define set_his_want_state_do set_my_want_state_will +#define set_his_want_state_will set_my_want_state_do + +#define set_his_state_dont set_my_state_wont +#define set_his_state_wont set_my_state_dont +#define set_his_want_state_dont set_my_want_state_wont +#define set_his_want_state_wont set_my_want_state_dont + + +extern FILE + *NetTrace; /* Where debugging output goes */ +extern unsigned char + NetTraceFile[]; /* Name of file where debugging output goes */ +extern void + SetNetTrace P((char *)); /* Function to change where debugging goes */ + +extern jmp_buf + peerdied, + toplevel; /* For error conditions. */ + +extern void + command P((int, char *, int)), + Dump P((int, unsigned char *, int)), + init_3270 P((void)), + printoption P((char *, int, int)), + printsub P((int, unsigned char *, int)), + sendnaws P((void)), + setconnmode P((int)), + setcommandmode P((void)), + setneturg P((void)), + sys_telnet_init P((void)), + telnet P((char *)), + tel_enter_binary P((int)), + TerminalFlushOutput P((void)), + TerminalNewMode P((int)), + TerminalRestoreState P((void)), + TerminalSaveState P((void)), + tninit P((void)), + upcase P((char *)), + willoption P((int)), + wontoption P((int)); + +extern void + send_do P((int, int)), + send_dont P((int, int)), + send_will P((int, int)), + send_wont P((int, int)); + +extern void + lm_will P((unsigned char *, int)), + lm_wont P((unsigned char *, int)), + lm_do P((unsigned char *, int)), + lm_dont P((unsigned char *, int)), + lm_mode P((unsigned char *, int, int)); + +extern void + slc_init P((void)), + slcstate P((void)), + slc_mode_export P((void)), + slc_mode_import P((int)), + slc_import P((int)), + slc_export P((void)), + slc P((unsigned char *, int)), + slc_check P((void)), + slc_start_reply P((void)), + slc_add_reply P((int, int, int)), + slc_end_reply P((void)); +extern int + slc_update P((void)); + +extern void + env_opt P((unsigned char *, int)), + env_opt_start P((void)), + env_opt_start_info P((void)), + env_opt_add P((unsigned char *)), + env_opt_end P((int)); + +extern unsigned char + *env_default P((int, int)), + *env_getvalue P((unsigned char *)); + +extern int + get_status P((void)), + dosynch P((void)); + +extern cc_t + *tcval P((int)); + +#ifndef USE_TERMIO + +extern struct tchars ntc; +extern struct ltchars nltc; +extern struct sgttyb nttyb; + +# define termEofChar ntc.t_eofc +# define termEraseChar nttyb.sg_erase +# define termFlushChar nltc.t_flushc +# define termIntChar ntc.t_intrc +# define termKillChar nttyb.sg_kill +# define termLiteralNextChar nltc.t_lnextc +# define termQuitChar ntc.t_quitc +# define termSuspChar nltc.t_suspc +# define termRprntChar nltc.t_rprntc +# define termWerasChar nltc.t_werasc +# define termStartChar ntc.t_startc +# define termStopChar ntc.t_stopc +# define termForw1Char ntc.t_brkc +extern cc_t termForw2Char; +extern cc_t termAytChar; + +# define termEofCharp (cc_t *)&ntc.t_eofc +# define termEraseCharp (cc_t *)&nttyb.sg_erase +# define termFlushCharp (cc_t *)&nltc.t_flushc +# define termIntCharp (cc_t *)&ntc.t_intrc +# define termKillCharp (cc_t *)&nttyb.sg_kill +# define termLiteralNextCharp (cc_t *)&nltc.t_lnextc +# define termQuitCharp (cc_t *)&ntc.t_quitc +# define termSuspCharp (cc_t *)&nltc.t_suspc +# define termRprntCharp (cc_t *)&nltc.t_rprntc +# define termWerasCharp (cc_t *)&nltc.t_werasc +# define termStartCharp (cc_t *)&ntc.t_startc +# define termStopCharp (cc_t *)&ntc.t_stopc +# define termForw1Charp (cc_t *)&ntc.t_brkc +# define termForw2Charp (cc_t *)&termForw2Char +# define termAytCharp (cc_t *)&termAytChar + +# else + +extern struct termio new_tc; + +# define termEofChar new_tc.c_cc[VEOF] +# define termEraseChar new_tc.c_cc[VERASE] +# define termIntChar new_tc.c_cc[VINTR] +# define termKillChar new_tc.c_cc[VKILL] +# define termQuitChar new_tc.c_cc[VQUIT] + +# ifndef VSUSP +extern cc_t termSuspChar; +# else +# define termSuspChar new_tc.c_cc[VSUSP] +# endif +# if defined(VFLUSHO) && !defined(VDISCARD) +# define VDISCARD VFLUSHO +# endif +# ifndef VDISCARD +extern cc_t termFlushChar; +# else +# define termFlushChar new_tc.c_cc[VDISCARD] +# endif +# ifndef VWERASE +extern cc_t termWerasChar; +# else +# define termWerasChar new_tc.c_cc[VWERASE] +# endif +# ifndef VREPRINT +extern cc_t termRprntChar; +# else +# define termRprntChar new_tc.c_cc[VREPRINT] +# endif +# ifndef VLNEXT +extern cc_t termLiteralNextChar; +# else +# define termLiteralNextChar new_tc.c_cc[VLNEXT] +# endif +# ifndef VSTART +extern cc_t termStartChar; +# else +# define termStartChar new_tc.c_cc[VSTART] +# endif +# ifndef VSTOP +extern cc_t termStopChar; +# else +# define termStopChar new_tc.c_cc[VSTOP] +# endif +# ifndef VEOL +extern cc_t termForw1Char; +# else +# define termForw1Char new_tc.c_cc[VEOL] +# endif +# ifndef VEOL2 +extern cc_t termForw2Char; +# else +# define termForw2Char new_tc.c_cc[VEOL] +# endif +# ifndef VSTATUS +extern cc_t termAytChar; +#else +# define termAytChar new_tc.c_cc[VSTATUS] +#endif + +# if !defined(CRAY) || defined(__STDC__) +# define termEofCharp &termEofChar +# define termEraseCharp &termEraseChar +# define termIntCharp &termIntChar +# define termKillCharp &termKillChar +# define termQuitCharp &termQuitChar +# define termSuspCharp &termSuspChar +# define termFlushCharp &termFlushChar +# define termWerasCharp &termWerasChar +# define termRprntCharp &termRprntChar +# define termLiteralNextCharp &termLiteralNextChar +# define termStartCharp &termStartChar +# define termStopCharp &termStopChar +# define termForw1Charp &termForw1Char +# define termForw2Charp &termForw2Char +# define termAytCharp &termAytChar +# else + /* Work around a compiler bug */ +# define termEofCharp 0 +# define termEraseCharp 0 +# define termIntCharp 0 +# define termKillCharp 0 +# define termQuitCharp 0 +# define termSuspCharp 0 +# define termFlushCharp 0 +# define termWerasCharp 0 +# define termRprntCharp 0 +# define termLiteralNextCharp 0 +# define termStartCharp 0 +# define termStopCharp 0 +# define termForw1Charp 0 +# define termForw2Charp 0 +# define termAytCharp 0 +# endif +#endif + + +/* Ring buffer structures which are shared */ + +extern Ring + netoring, + netiring, + ttyoring, + ttyiring; + +/* Tn3270 section */ +#if defined(TN3270) + +extern int + HaveInput, /* Whether an asynchronous I/O indication came in */ + noasynchtty, /* Don't do signals on I/O (SIGURG, SIGIO) */ + noasynchnet, /* Don't do signals on I/O (SIGURG, SIGIO) */ + sigiocount, /* Count of SIGIO receptions */ + shell_active; /* Subshell is active */ + +extern char + *Ibackp, /* Oldest byte of 3270 data */ + Ibuf[], /* 3270 buffer */ + *Ifrontp, /* Where next 3270 byte goes */ + tline[], + *transcom; /* Transparent command */ + +extern int + settranscom P((int, char**)); + +extern void + inputAvailable P((int)); +#endif /* defined(TN3270) */ diff --git a/telnet.tproj/fdset.h b/telnet.tproj/fdset.h new file mode 100644 index 0000000..d0f290a --- /dev/null +++ b/telnet.tproj/fdset.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fdset.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * The following is defined just in case someone should want to run + * this telnet on a 4.2 system. + * + */ + +#ifndef FD_SETSIZE + +#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) +#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) +#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) +#define FD_ZERO(p) ((p)->fds_bits[0] = 0) + +#endif diff --git a/telnet.tproj/general.h b/telnet.tproj/general.h new file mode 100644 index 0000000..303ae14 --- /dev/null +++ b/telnet.tproj/general.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)general.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Some general definitions. + */ + + +#define numberof(x) (sizeof x/sizeof x[0]) +#define highestof(x) (numberof(x)-1) + +#define ClearElement(x) memset((char *)&x, 0, sizeof x) +#define ClearArray(x) memset((char *)x, 0, sizeof x) diff --git a/telnet.tproj/krb4-proto.h b/telnet.tproj/krb4-proto.h new file mode 100644 index 0000000..9f3f0b0 --- /dev/null +++ b/telnet.tproj/krb4-proto.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +#ifdef __STDC__ +# define P(s) s +#else +# define P(s) () +#endif + +/* add_ticket.c */ +int add_ticket P((KTEXT , int , char *, int , char *, char *, char *, int , KTEXT )); + +/* cr_err_reply.c */ +void cr_err_reply P((KTEXT , char *, char *, char *, u_long , u_long , char *)); + +/* create_auth_reply.c */ +KTEXT create_auth_reply P((char *, char *, char *, long , int , unsigned long , int , KTEXT )); + +/* create_ciph.c */ +int create_ciph P((KTEXT , C_Block , char *, char *, char *, unsigned long , int , KTEXT , unsigned long , C_Block )); + +/* create_death_packet.c */ +KTEXT krb_create_death_packet P((char *)); + +/* create_ticket.c */ +int krb_create_ticket P((KTEXT , unsigned int , char *, char *, char *, long , char *, int , long , char *, char *, C_Block )); + +/* debug_decl.c */ + +/* decomp_ticket.c */ +int decomp_ticket P((KTEXT , unsigned char *, char *, char *, char *, unsigned long *, C_Block , int *, unsigned long *, char *, char *, C_Block , Key_schedule )); + +/* dest_tkt.c */ +int dest_tkt P((void )); + +/* extract_ticket.c */ +int extract_ticket P((KTEXT , int , char *, int *, int *, char *, KTEXT )); + +/* fgetst.c */ +int fgetst P((FILE *, char *, int )); + +/* get_ad_tkt.c */ +int get_ad_tkt P((char *, char *, char *, int )); + +/* get_admhst.c */ +int krb_get_admhst P((char *, char *, int )); + +/* get_cred.c */ +int krb_get_cred P((char *, char *, char *, CREDENTIALS *)); + +/* get_in_tkt.c */ +int krb_get_pw_in_tkt P((char *, char *, char *, char *, char *, int , char *)); +int placebo_read_password P((des_cblock *, char *, int )); +int placebo_read_pw_string P((char *, int , char *, int )); + +/* get_krbhst.c */ +int krb_get_krbhst P((char *, char *, int )); + +/* get_krbrlm.c */ +int krb_get_lrealm P((char *, int )); + +/* get_phost.c */ +char *krb_get_phost P((char *)); + +/* get_pw_tkt.c */ +int get_pw_tkt P((char *, char *, char *, char *)); + +/* get_request.c */ +int get_request P((KTEXT , int , char **, char **)); + +/* get_svc_in_tkt.c */ +int krb_get_svc_in_tkt P((char *, char *, char *, char *, char *, int , char *)); + +/* get_tf_fullname.c */ +int krb_get_tf_fullname P((char *, char *, char *, char *)); + +/* get_tf_realm.c */ +int krb_get_tf_realm P((char *, char *)); + +/* getopt.c */ +int getopt P((int , char **, char *)); + +/* getrealm.c */ +char *krb_realmofhost P((char *)); + +/* getst.c */ +int getst P((int , char *, int )); + +/* in_tkt.c */ +int in_tkt P((char *, char *)); + +/* k_gethostname.c */ +int k_gethostname P((char *, int )); + +/* klog.c */ +char *klog P((int , char *, int , int , int , int , int , int , int , int , int , int )); +int kset_logfile P((char *)); + +/* kname_parse.c */ +int kname_parse P((char *, char *, char *, char *)); +int k_isname P((char *)); +int k_isinst P((char *)); +int k_isrealm P((char *)); + +/* kntoln.c */ +int krb_kntoln P((AUTH_DAT *, char *)); + +/* krb_err_txt.c */ + +/* krb_get_in_tkt.c */ +int krb_get_in_tkt P((char *, char *, char *, char *, char *, int , int (*key_proc )(), int (*decrypt_proc )(), char *)); + +/* kuserok.c */ +int kuserok P((AUTH_DAT *, char *)); + +/* log.c */ +void log P((char *, int , int , int , int , int , int , int , int , int , int )); +int set_logfile P((char *)); +int new_log P((long , char *)); + +/* mk_err.c */ +long krb_mk_err P((u_char *, long , char *)); + +/* mk_priv.c */ +long krb_mk_priv P((u_char *, u_char *, u_long , Key_schedule , C_Block , struct sockaddr_in *, struct sockaddr_in *)); + +/* mk_req.c */ +int krb_mk_req P((KTEXT , char *, char *, char *, long )); +int krb_set_lifetime P((int )); + +/* mk_safe.c */ +long krb_mk_safe P((u_char *, u_char *, u_long , C_Block *, struct sockaddr_in *, struct sockaddr_in *)); + +/* month_sname.c */ +char *month_sname P((int )); + +/* netread.c */ +int krb_net_read P((int , char *, int )); + +/* netwrite.c */ +int krb_net_write P((int , char *, int )); + +/* one.c */ + +/* pkt_cipher.c */ +KTEXT pkt_cipher P((KTEXT )); + +/* pkt_clen.c */ +int pkt_clen P((KTEXT )); + +/* rd_err.c */ +int krb_rd_err P((u_char *, u_long , long *, MSG_DAT *)); + +/* rd_priv.c */ +long krb_rd_priv P((u_char *, u_long , Key_schedule , C_Block , struct sockaddr_in *, struct sockaddr_in *, MSG_DAT *)); + +/* rd_req.c */ +int krb_set_key P((char *, int )); +int krb_rd_req P((KTEXT , char *, char *, long , AUTH_DAT *, char *)); + +/* rd_safe.c */ +long krb_rd_safe P((u_char *, u_long , C_Block *, struct sockaddr_in *, struct sockaddr_in *, MSG_DAT *)); + +/* read_service_key.c */ +int read_service_key P((char *, char *, char *, int , char *, char *)); + +/* recvauth.c */ +int krb_recvauth P((long , int , KTEXT , char *, char *, struct sockaddr_in *, struct sockaddr_in *, AUTH_DAT *, char *, Key_schedule , char *)); + +/* save_credentials.c */ +int save_credentials P((char *, char *, char *, C_Block , int , int , KTEXT , long )); + +/* send_to_kdc.c */ +int send_to_kdc P((KTEXT , KTEXT , char *)); + +/* sendauth.c */ +int krb_sendauth P((long , int , KTEXT , char *, char *, char *, u_long , MSG_DAT *, CREDENTIALS *, Key_schedule , struct sockaddr_in *, struct sockaddr_in *, char *)); +int krb_sendsvc P((int , char *)); + +/* setenv.c */ +int setenv P((char *, char *, int )); +void unsetenv P((char *)); +char *getenv P((char *)); +char *_findenv P((char *, int *)); + +/* stime.c */ +char *stime P((long *)); + +/* tf_shm.c */ +int krb_shm_create P((char *)); +int krb_is_diskless P((void )); +int krb_shm_dest P((char *)); + +/* tf_util.c */ +int tf_init P((char *, int )); +int tf_get_pname P((char *)); +int tf_get_pinst P((char *)); +int tf_get_cred P((CREDENTIALS *)); +int tf_close P((void )); +int tf_save_cred P((char *, char *, char *, C_Block , int , int , KTEXT , long )); + +/* tkt_string.c */ +char *tkt_string P((void )); +void krb_set_tkt_string P((char *)); + +/* util.c */ +int ad_print P((AUTH_DAT *)); +int placebo_cblock_print P((des_cblock )); + +#undef P diff --git a/telnet.tproj/main.c b/telnet.tproj/main.c new file mode 100644 index 0000000..94cbfc8 --- /dev/null +++ b/telnet.tproj/main.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include + +#include "ring.h" +#include "externs.h" +#include "defines.h" + +/* These values need to be the same as defined in libtelnet/kerberos5.c */ +/* Either define them in both places, or put in some common header file. */ +#define OPTS_FORWARD_CREDS 0x00000002 +#define OPTS_FORWARDABLE_CREDS 0x00000001 + +#if 0 +#define FORWARD +#endif + +/* + * Initialize variables. + */ + void +tninit() +{ + init_terminal(); + + init_network(); + + init_telnet(); + + init_sys(); + +#if defined(TN3270) + init_3270(); +#endif +} + + void +usage() +{ + fprintf(stderr, "Usage: %s %s%s%s%s\n", + prompt, +#ifdef AUTHENTICATION + "[-8] [-E] [-K] [-L] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]", + "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] ", +#else + "[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]", + "\n\t[-n tracefile]", +#endif +#if defined(TN3270) && (defined(unix) || defined(__APPLE__)) +# ifdef AUTHENTICATION + "[-noasynch] [-noasynctty]\n\t[-noasyncnet] [-r] [-t transcom] ", +# else + "[-noasynch] [-noasynctty] [-noasyncnet] [-r]\n\t[-t transcom]", +# endif +#else + "[-r] ", +#endif +#ifdef ENCRYPTION + "[-x] [host-name [port]]" +#else /* ENCRYPTION */ + "[host-name [port]]" +#endif /* ENCRYPTION */ + ); + exit(1); +} + +/* + * main. Parse arguments, invoke the protocol or command parser. + */ + + +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + int ch; + char *user, *strrchr(); +#ifdef FORWARD + extern int forward_flags; +#endif /* FORWARD */ + + tninit(); /* Clear out things */ +#if defined(CRAY) && !defined(__STDC__) + _setlist_init(); /* Work around compiler bug */ +#endif + + TerminalSaveState(); + + if (prompt = strrchr(argv[0], '/')) + ++prompt; + else + prompt = argv[0]; + + user = NULL; + + rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE; + autologin = -1; + + while ((ch = getopt(argc, argv, "8EKLS:X:acde:fFk:l:n:rt:x")) != EOF) { + switch(ch) { + case '8': + eight = 3; /* binary output and input */ + break; + case 'E': + rlogin = escape = _POSIX_VDISABLE; + break; + case 'K': +#ifdef AUTHENTICATION + autologin = 0; +#endif + break; + case 'L': + eight |= 2; /* binary output only */ + break; + case 'S': + { +#ifdef HAS_GETTOS + extern int tos; + + if ((tos = parsetos(optarg, "tcp")) < 0) + fprintf(stderr, "%s%s%s%s\n", + prompt, ": Bad TOS argument '", + optarg, + "; will try to use default TOS"); +#else + fprintf(stderr, + "%s: Warning: -S ignored, no parsetos() support.\n", + prompt); +#endif + } + break; + case 'X': +#ifdef AUTHENTICATION + auth_disable_name(optarg); +#endif + break; + case 'a': + autologin = 1; + break; + case 'c': + skiprc = 1; + break; + case 'd': + debug = 1; + break; + case 'e': + set_escape_char(optarg); + break; + case 'f': +#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) + if (forward_flags & OPTS_FORWARD_CREDS) { + fprintf(stderr, + "%s: Only one of -f and -F allowed.\n", + prompt); + usage(); + } + forward_flags |= OPTS_FORWARD_CREDS; +#else + fprintf(stderr, + "%s: Warning: -f ignored, no Kerberos V5 support.\n", + prompt); +#endif + break; + case 'F': +#if defined(AUTHENTICATION) && defined(KRB5) && defined(FORWARD) + if (forward_flags & OPTS_FORWARD_CREDS) { + fprintf(stderr, + "%s: Only one of -f and -F allowed.\n", + prompt); + usage(); + } + forward_flags |= OPTS_FORWARD_CREDS; + forward_flags |= OPTS_FORWARDABLE_CREDS; +#else + fprintf(stderr, + "%s: Warning: -F ignored, no Kerberos V5 support.\n", + prompt); +#endif + break; + case 'k': +#if defined(AUTHENTICATION) && defined(KRB4) + { + extern char *dest_realm, dst_realm_buf[], dst_realm_sz; + dest_realm = dst_realm_buf; + (void)strncpy(dest_realm, optarg, dst_realm_sz); + } +#else + fprintf(stderr, + "%s: Warning: -k ignored, no Kerberos V4 support.\n", + prompt); +#endif + break; + case 'l': + autologin = 1; + user = optarg; + break; + case 'n': +#if defined(TN3270) && (defined(unix) || defined(__APPLE__)) + /* distinguish between "-n oasynch" and "-noasynch" */ + if (argv[optind - 1][0] == '-' && argv[optind - 1][1] + == 'n' && argv[optind - 1][2] == 'o') { + if (!strcmp(optarg, "oasynch")) { + noasynchtty = 1; + noasynchnet = 1; + } else if (!strcmp(optarg, "oasynchtty")) + noasynchtty = 1; + else if (!strcmp(optarg, "oasynchnet")) + noasynchnet = 1; + } else +#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */ + SetNetTrace(optarg); + break; + case 'r': + rlogin = '~'; + break; + case 't': +#if defined(TN3270) && (defined(unix) || defined(__APPLE__)) + transcom = tline; + (void)strcpy(transcom, optarg); +#else + fprintf(stderr, + "%s: Warning: -t ignored, no TN3270 support.\n", + prompt); +#endif + break; + case 'x': +#ifdef ENCRYPTION + encrypt_auto(1); + decrypt_auto(1); +#else /* ENCRYPTION */ + fprintf(stderr, + "%s: Warning: -x ignored, no ENCRYPT support.\n", + prompt); +#endif /* ENCRYPTION */ + break; + case '?': + default: + usage(); + /* NOTREACHED */ + } + } + if (autologin == -1) + autologin = (rlogin == _POSIX_VDISABLE) ? 0 : 1; + + argc -= optind; + argv += optind; + + if (argc) { + char *args[7], **argp = args; + + if (argc > 2) + usage(); + *argp++ = prompt; + if (user) { + *argp++ = "-l"; + *argp++ = user; + } + *argp++ = argv[0]; /* host */ + if (argc > 1) + *argp++ = argv[1]; /* port */ + *argp = 0; + + if (setjmp(toplevel) != 0) + Exit(0); + if (tn(argp - args, args) == 1) + return (0); + else + return (1); + } + (void)setjmp(toplevel); + for (;;) { +#ifdef TN3270 + if (shell_active) + shell_continue(); + else +#endif + command(1, 0, 0); + } +} diff --git a/telnet.tproj/network.c b/telnet.tproj/network.c new file mode 100644 index 0000000..27cc7bd --- /dev/null +++ b/telnet.tproj/network.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)network.c 8.2 (Berkeley) 12/15/93"; +#endif /* not lint */ + +#include +#include +#include + +#include + +#include + +#include "ring.h" + +#include "defines.h" +#include "externs.h" +#include "fdset.h" + +Ring netoring, netiring; +unsigned char netobuf[2*BUFSIZ], netibuf[BUFSIZ]; + +/* + * Initialize internal network data structures. + */ + + void +init_network() +{ + if (ring_init(&netoring, netobuf, sizeof netobuf) != 1) { + exit(1); + } + if (ring_init(&netiring, netibuf, sizeof netibuf) != 1) { + exit(1); + } + NetTrace = stdout; +} + + +/* + * Check to see if any out-of-band data exists on a socket (for + * Telnet "synch" processing). + */ + + int +stilloob() +{ + static struct timeval timeout = { 0 }; + fd_set excepts; + int value; + + do { + FD_ZERO(&excepts); + FD_SET(net, &excepts); + value = select(net+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); + } while ((value == -1) && (errno == EINTR)); + + if (value < 0) { + perror("select"); + (void) quit(); + /* NOTREACHED */ + } + if (FD_ISSET(net, &excepts)) { + return 1; + } else { + return 0; + } +} + + +/* + * setneturg() + * + * Sets "neturg" to the current location. + */ + + void +setneturg() +{ + ring_mark(&netoring); +} + + +/* + * netflush + * Send as much data as possible to the network, + * handling requests for urgent data. + * + * The return value indicates whether we did any + * useful work. + */ + + + int +netflush() +{ + register int n, n1; + +#ifdef ENCRYPTION + if (encrypt_output) + ring_encrypt(&netoring, encrypt_output); +#endif /* ENCRYPTION */ + if ((n1 = n = ring_full_consecutive(&netoring)) > 0) { + if (!ring_at_mark(&netoring)) { + n = send(net, (char *)netoring.consume, n, 0); /* normal write */ + } else { + /* + * In 4.2 (and 4.3) systems, there is some question about + * what byte in a sendOOB operation is the "OOB" data. + * To make ourselves compatible, we only send ONE byte + * out of band, the one WE THINK should be OOB (though + * we really have more the TCP philosophy of urgent data + * rather than the Unix philosophy of OOB data). + */ + n = send(net, (char *)netoring.consume, 1, MSG_OOB);/* URGENT data */ + } + } + if (n < 0) { + if (errno != ENOBUFS && errno != EWOULDBLOCK) { + setcommandmode(); + perror(hostname); + (void)NetClose(net); + ring_clear_mark(&netoring); + longjmp(peerdied, -1); + /*NOTREACHED*/ + } + n = 0; + } + if (netdata && n) { + Dump('>', netoring.consume, n); + } + if (n) { + ring_consumed(&netoring, n); + /* + * If we sent all, and more to send, then recurse to pick + * up the other half. + */ + if ((n1 == n) && ring_full_consecutive(&netoring)) { + (void) netflush(); + } + return 1; + } else { + return 0; + } +} diff --git a/telnet.tproj/ring.c b/telnet.tproj/ring.c new file mode 100644 index 0000000..6506ae1 --- /dev/null +++ b/telnet.tproj/ring.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + +/* + * This defines a structure for a ring buffer. + * + * The circular buffer has two parts: + *((( + * full: [consume, supply) + * empty: [supply, consume) + *]]] + * + */ + +#include +#include + +#ifdef size_t +#undef size_t +#endif + +#include +#ifndef FILIO_H +#include +#endif +#include + +#include "ring.h" +#include "general.h" + +/* Internal macros */ + +#if !defined(MIN) +#define MIN(a,b) (((a)<(b))? (a):(b)) +#endif /* !defined(MIN) */ + +#define ring_subtract(d,a,b) (((a)-(b) >= 0)? \ + (a)-(b): (((a)-(b))+(d)->size)) + +#define ring_increment(d,a,c) (((a)+(c) < (d)->top)? \ + (a)+(c) : (((a)+(c))-(d)->size)) + +#define ring_decrement(d,a,c) (((a)-(c) >= (d)->bottom)? \ + (a)-(c) : (((a)-(c))-(d)->size)) + + +/* + * The following is a clock, used to determine full, empty, etc. + * + * There is some trickiness here. Since the ring buffers are initialized + * to ZERO on allocation, we need to make sure, when interpreting the + * clock, that when the times are EQUAL, then the buffer is FULL. + */ +static u_long ring_clock = 0; + + +#define ring_empty(d) (((d)->consume == (d)->supply) && \ + ((d)->consumetime >= (d)->supplytime)) +#define ring_full(d) (((d)->supply == (d)->consume) && \ + ((d)->supplytime > (d)->consumetime)) + + + + + +/* Buffer state transition routines */ + + ring_init(ring, buffer, count) +Ring *ring; + unsigned char *buffer; + int count; +{ + memset((char *)ring, 0, sizeof *ring); + + ring->size = count; + + ring->supply = ring->consume = ring->bottom = buffer; + + ring->top = ring->bottom+ring->size; + +#ifdef ENCRYPTION + ring->clearto = 0; +#endif /* ENCRYPTION */ + + return 1; +} + +/* Mark routines */ + +/* + * Mark the most recently supplied byte. + */ + + void +ring_mark(ring) + Ring *ring; +{ + ring->mark = ring_decrement(ring, ring->supply, 1); +} + +/* + * Is the ring pointing to the mark? + */ + + int +ring_at_mark(ring) + Ring *ring; +{ + if (ring->mark == ring->consume) { + return 1; + } else { + return 0; + } +} + +/* + * Clear any mark set on the ring. + */ + + void +ring_clear_mark(ring) + Ring *ring; +{ + ring->mark = 0; +} + +/* + * Add characters from current segment to ring buffer. + */ + void +ring_supplied(ring, count) + Ring *ring; + int count; +{ + ring->supply = ring_increment(ring, ring->supply, count); + ring->supplytime = ++ring_clock; +} + +/* + * We have just consumed "c" bytes. + */ + void +ring_consumed(ring, count) + Ring *ring; + int count; +{ + if (count == 0) /* don't update anything */ + return; + + if (ring->mark && + (ring_subtract(ring, ring->mark, ring->consume) < count)) { + ring->mark = 0; + } +#ifdef ENCRYPTION + if (ring->consume < ring->clearto && + ring->clearto <= ring->consume + count) + ring->clearto = 0; + else if (ring->consume + count > ring->top && + ring->bottom <= ring->clearto && + ring->bottom + ((ring->consume + count) - ring->top)) + ring->clearto = 0; +#endif /* ENCRYPTION */ + ring->consume = ring_increment(ring, ring->consume, count); + ring->consumetime = ++ring_clock; + /* + * Try to encourage "ring_empty_consecutive()" to be large. + */ + if (ring_empty(ring)) { + ring->consume = ring->supply = ring->bottom; + } +} + + + +/* Buffer state query routines */ + + +/* Number of bytes that may be supplied */ + int +ring_empty_count(ring) + Ring *ring; +{ + if (ring_empty(ring)) { /* if empty */ + return ring->size; + } else { + return ring_subtract(ring, ring->consume, ring->supply); + } +} + +/* number of CONSECUTIVE bytes that may be supplied */ + int +ring_empty_consecutive(ring) + Ring *ring; +{ + if ((ring->consume < ring->supply) || ring_empty(ring)) { + /* + * if consume is "below" supply, or empty, then + * return distance to the top + */ + return ring_subtract(ring, ring->top, ring->supply); + } else { + /* + * else, return what we may. + */ + return ring_subtract(ring, ring->consume, ring->supply); + } +} + +/* Return the number of bytes that are available for consuming + * (but don't give more than enough to get to cross over set mark) + */ + + int +ring_full_count(ring) + Ring *ring; +{ + if ((ring->mark == 0) || (ring->mark == ring->consume)) { + if (ring_full(ring)) { + return ring->size; /* nothing consumed, but full */ + } else { + return ring_subtract(ring, ring->supply, ring->consume); + } + } else { + return ring_subtract(ring, ring->mark, ring->consume); + } +} + +/* + * Return the number of CONSECUTIVE bytes available for consuming. + * However, don't return more than enough to cross over set mark. + */ + int +ring_full_consecutive(ring) + Ring *ring; +{ + if ((ring->mark == 0) || (ring->mark == ring->consume)) { + if ((ring->supply < ring->consume) || ring_full(ring)) { + return ring_subtract(ring, ring->top, ring->consume); + } else { + return ring_subtract(ring, ring->supply, ring->consume); + } + } else { + if (ring->mark < ring->consume) { + return ring_subtract(ring, ring->top, ring->consume); + } else { /* Else, distance to mark */ + return ring_subtract(ring, ring->mark, ring->consume); + } + } +} + +/* + * Move data into the "supply" portion of of the ring buffer. + */ + void +ring_supply_data(ring, buffer, count) + Ring *ring; + unsigned char *buffer; + int count; +{ + int i; + + while (count) { + i = MIN(count, ring_empty_consecutive(ring)); + memmove(ring->supply, buffer, i); + ring_supplied(ring, i); + count -= i; + buffer += i; + } +} + +#ifdef notdef + +/* + * Move data from the "consume" portion of the ring buffer + */ + void +ring_consume_data(ring, buffer, count) + Ring *ring; + unsigned char *buffer; + int count; +{ + int i; + + while (count) { + i = MIN(count, ring_full_consecutive(ring)); + memmove(buffer, ring->consume, i); + ring_consumed(ring, i); + count -= i; + buffer += i; + } +} +#endif + +#ifdef ENCRYPTION + void +ring_encrypt(ring, encryptor) + Ring *ring; + void (*encryptor)(); +{ + unsigned char *s, *c; + + if (ring_empty(ring) || ring->clearto == ring->supply) + return; + + if (!(c = ring->clearto)) + c = ring->consume; + + s = ring->supply; + + if (s <= c) { + (*encryptor)(c, ring->top - c); + (*encryptor)(ring->bottom, s - ring->bottom); + } else + (*encryptor)(c, s - c); + + ring->clearto = ring->supply; +} + + void +ring_clearto(ring) + Ring *ring; +{ + if (!ring_empty(ring)) + ring->clearto = ring->supply; + else + ring->clearto = 0; +} +#endif /* ENCRYPTION */ diff --git a/telnet.tproj/ring.h b/telnet.tproj/ring.h new file mode 100644 index 0000000..a9ef843 --- /dev/null +++ b/telnet.tproj/ring.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ring.h 8.1 (Berkeley) 6/6/93 + */ + +#if defined(P) +# undef P +#endif + +#if defined(__STDC__) || defined(LINT_ARGS) +# define P(x) x +#else +# define P(x) () +#endif + +/* + * This defines a structure for a ring buffer. + * + * The circular buffer has two parts: + *((( + * full: [consume, supply) + * empty: [supply, consume) + *]]] + * + */ +typedef struct { + unsigned char *consume, /* where data comes out of */ + *supply, /* where data comes in to */ + *bottom, /* lowest address in buffer */ + *top, /* highest address+1 in buffer */ + *mark; /* marker (user defined) */ +#ifdef ENCRYPTION + unsigned char *clearto; /* Data to this point is clear text */ + unsigned char *encryyptedto; /* Data is encrypted to here */ +#endif /* ENCRYPTION */ + int size; /* size in bytes of buffer */ + u_long consumetime, /* help us keep straight full, empty, etc. */ + supplytime; +} Ring; + +/* Here are some functions and macros to deal with the ring buffer */ + +/* Initialization routine */ +extern int + ring_init P((Ring *ring, unsigned char *buffer, int count)); + +/* Data movement routines */ +extern void + ring_supply_data P((Ring *ring, unsigned char *buffer, int count)); +#ifdef notdef +extern void + ring_consume_data P((Ring *ring, unsigned char *buffer, int count)); +#endif + +/* Buffer state transition routines */ +extern void + ring_supplied P((Ring *ring, int count)), + ring_consumed P((Ring *ring, int count)); + +/* Buffer state query routines */ +extern int + ring_empty_count P((Ring *ring)), + ring_empty_consecutive P((Ring *ring)), + ring_full_count P((Ring *ring)), + ring_full_consecutive P((Ring *ring)); + +#ifdef ENCRYPTION +extern void + ring_encrypt P((Ring *ring, void (*func)())), + ring_clearto P((Ring *ring)); +#endif /* ENCRYPTION */ + +extern void + ring_clear_mark(), + ring_mark(); diff --git a/telnet.tproj/sys_bsd.c b/telnet.tproj/sys_bsd.c new file mode 100644 index 0000000..8455d4d --- /dev/null +++ b/telnet.tproj/sys_bsd.c @@ -0,0 +1,1243 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)sys_bsd.c 8.4 (Berkeley) 5/30/95"; +#endif /* not lint */ + +/* + * The following routines try to encapsulate what is system dependent + * (at least between 4.x and dos) which is used in telnet.c. + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "ring.h" + +#include "fdset.h" + +#include "defines.h" +#include "externs.h" +#include "types.h" + +#if defined(CRAY) || (defined(USE_TERMIO) && !defined(SYSV_TERMIO)) +#define SIG_FUNC_RET void +#else +#define SIG_FUNC_RET int +#endif + +#ifdef SIGINFO +extern SIG_FUNC_RET ayt_status(); +#endif + +int + tout, /* Output file descriptor */ + tin, /* Input file descriptor */ + net; + +#ifndef USE_TERMIO +struct tchars otc = { 0 }, ntc = { 0 }; +struct ltchars oltc = { 0 }, nltc = { 0 }; +struct sgttyb ottyb = { 0 }, nttyb = { 0 }; +int olmode = 0; +# define cfgetispeed(ptr) (ptr)->sg_ispeed +# define cfgetospeed(ptr) (ptr)->sg_ospeed +# define old_tc ottyb + +#else /* USE_TERMIO */ +struct termio old_tc = { 0 }; +extern struct termio new_tc; + +# ifndef TCSANOW +# ifdef TCSETS +# define TCSANOW TCSETS +# define TCSADRAIN TCSETSW +# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) +# else +# ifdef TCSETA +# define TCSANOW TCSETA +# define TCSADRAIN TCSETAW +# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) +# else +# define TCSANOW TIOCSETA +# define TCSADRAIN TIOCSETAW +# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) +# endif +# endif +# define tcsetattr(f, a, t) ioctl(f, a, (char *)t) +# define cfgetospeed(ptr) ((ptr)->c_cflag&CBAUD) +# ifdef CIBAUD +# define cfgetispeed(ptr) (((ptr)->c_cflag&CIBAUD) >> IBSHIFT) +# else +# define cfgetispeed(ptr) cfgetospeed(ptr) +# endif +# endif /* TCSANOW */ +# ifdef sysV88 +# define TIOCFLUSH TC_PX_DRAIN +# endif +#endif /* USE_TERMIO */ + +static fd_set ibits, obits, xbits; + + + void +init_sys() +{ + tout = fileno(stdout); + tin = fileno(stdin); + FD_ZERO(&ibits); + FD_ZERO(&obits); + FD_ZERO(&xbits); + + errno = 0; +} + + + int +TerminalWrite(buf, n) + char *buf; + int n; +{ + return write(tout, buf, n); +} + + int +TerminalRead(buf, n) + char *buf; + int n; +{ + return read(tin, buf, n); +} + +/* + * + */ + + int +TerminalAutoFlush() +{ +#if defined(LNOFLSH) + int flush; + + ioctl(0, TIOCLGET, (char *)&flush); + return !(flush&LNOFLSH); /* if LNOFLSH, no autoflush */ +#else /* LNOFLSH */ + return 1; +#endif /* LNOFLSH */ +} + +#ifdef KLUDGELINEMODE +extern int kludgelinemode; +#endif +/* + * TerminalSpecialChars() + * + * Look at an input character to see if it is a special character + * and decide what to do. + * + * Output: + * + * 0 Don't add this character. + * 1 Do add this character + */ + +extern void xmitAO(), xmitEL(), xmitEC(), intp(), sendbrk(); + + int +TerminalSpecialChars(c) + int c; +{ + if (c == termIntChar) { + intp(); + return 0; + } else if (c == termQuitChar) { +#ifdef KLUDGELINEMODE + if (kludgelinemode) + sendbrk(); + else +#endif + sendabort(); + return 0; + } else if (c == termEofChar) { + if (my_want_state_is_will(TELOPT_LINEMODE)) { + sendeof(); + return 0; + } + return 1; + } else if (c == termSuspChar) { + sendsusp(); + return(0); + } else if (c == termFlushChar) { + xmitAO(); /* Transmit Abort Output */ + return 0; + } else if (!MODE_LOCAL_CHARS(globalmode)) { + if (c == termKillChar) { + xmitEL(); + return 0; + } else if (c == termEraseChar) { + xmitEC(); /* Transmit Erase Character */ + return 0; + } + } + return 1; +} + + +/* + * Flush output to the terminal + */ + + void +TerminalFlushOutput() +{ +#ifdef TIOCFLUSH + (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0); +#else + (void) ioctl(fileno(stdout), TCFLSH, (char *) 0); +#endif +} + + void +TerminalSaveState() +{ +#ifndef USE_TERMIO + ioctl(0, TIOCGETP, (char *)&ottyb); + ioctl(0, TIOCGETC, (char *)&otc); + ioctl(0, TIOCGLTC, (char *)&oltc); + ioctl(0, TIOCLGET, (char *)&olmode); + + ntc = otc; + nltc = oltc; + nttyb = ottyb; + +#else /* USE_TERMIO */ + tcgetattr(0, &old_tc); + + new_tc = old_tc; + +#ifndef VDISCARD + termFlushChar = CONTROL('O'); +#endif +#ifndef VWERASE + termWerasChar = CONTROL('W'); +#endif +#ifndef VREPRINT + termRprntChar = CONTROL('R'); +#endif +#ifndef VLNEXT + termLiteralNextChar = CONTROL('V'); +#endif +#ifndef VSTART + termStartChar = CONTROL('Q'); +#endif +#ifndef VSTOP + termStopChar = CONTROL('S'); +#endif +#ifndef VSTATUS + termAytChar = CONTROL('T'); +#endif +#endif /* USE_TERMIO */ +} + + cc_t * +tcval(func) + register int func; +{ + switch(func) { + case SLC_IP: return(&termIntChar); + case SLC_ABORT: return(&termQuitChar); + case SLC_EOF: return(&termEofChar); + case SLC_EC: return(&termEraseChar); + case SLC_EL: return(&termKillChar); + case SLC_XON: return(&termStartChar); + case SLC_XOFF: return(&termStopChar); + case SLC_FORW1: return(&termForw1Char); +#ifdef USE_TERMIO + case SLC_FORW2: return(&termForw2Char); +# ifdef VDISCARD + case SLC_AO: return(&termFlushChar); +# endif +# ifdef VSUSP + case SLC_SUSP: return(&termSuspChar); +# endif +# ifdef VWERASE + case SLC_EW: return(&termWerasChar); +# endif +# ifdef VREPRINT + case SLC_RP: return(&termRprntChar); +# endif +# ifdef VLNEXT + case SLC_LNEXT: return(&termLiteralNextChar); +# endif +# ifdef VSTATUS + case SLC_AYT: return(&termAytChar); +# endif +#endif + + case SLC_SYNCH: + case SLC_BRK: + case SLC_EOR: + default: + return((cc_t *)0); + } +} + + void +TerminalDefaultChars() +{ +#ifndef USE_TERMIO + ntc = otc; + nltc = oltc; + nttyb.sg_kill = ottyb.sg_kill; + nttyb.sg_erase = ottyb.sg_erase; +#else /* USE_TERMIO */ + memmove(new_tc.c_cc, old_tc.c_cc, sizeof(old_tc.c_cc)); +# ifndef VDISCARD + termFlushChar = CONTROL('O'); +# endif +# ifndef VWERASE + termWerasChar = CONTROL('W'); +# endif +# ifndef VREPRINT + termRprntChar = CONTROL('R'); +# endif +# ifndef VLNEXT + termLiteralNextChar = CONTROL('V'); +# endif +# ifndef VSTART + termStartChar = CONTROL('Q'); +# endif +# ifndef VSTOP + termStopChar = CONTROL('S'); +# endif +# ifndef VSTATUS + termAytChar = CONTROL('T'); +# endif +#endif /* USE_TERMIO */ +} + +#ifdef notdef +void +TerminalRestoreState() +{ +} +#endif + +/* + * TerminalNewMode - set up terminal to a specific mode. + * MODE_ECHO: do local terminal echo + * MODE_FLOW: do local flow control + * MODE_TRAPSIG: do local mapping to TELNET IAC sequences + * MODE_EDIT: do local line editing + * + * Command mode: + * MODE_ECHO|MODE_EDIT|MODE_FLOW|MODE_TRAPSIG + * local echo + * local editing + * local xon/xoff + * local signal mapping + * + * Linemode: + * local/no editing + * Both Linemode and Single Character mode: + * local/remote echo + * local/no xon/xoff + * local/no signal mapping + */ + + + void +TerminalNewMode(f) + register int f; +{ + static int prevmode = 0; +#ifndef USE_TERMIO + struct tchars tc; + struct ltchars ltc; + struct sgttyb sb; + int lmode; +#else /* USE_TERMIO */ + struct termio tmp_tc; +#endif /* USE_TERMIO */ + int onoff; + int old; + cc_t esc; + + globalmode = f&~MODE_FORCE; + if (prevmode == f) + return; + + /* + * Write any outstanding data before switching modes + * ttyflush() returns 0 only when there is no more data + * left to write out, it returns -1 if it couldn't do + * anything at all, otherwise it returns 1 + the number + * of characters left to write. +#ifndef USE_TERMIO + * We would really like ask the kernel to wait for the output + * to drain, like we can do with the TCSADRAIN, but we don't have + * that option. The only ioctl that waits for the output to + * drain, TIOCSETP, also flushes the input queue, which is NOT + * what we want (TIOCSETP is like TCSADFLUSH). +#endif + */ + old = ttyflush(SYNCHing|flushout); + if (old < 0 || old > 1) { +#ifdef USE_TERMIO + tcgetattr(tin, &tmp_tc); +#endif /* USE_TERMIO */ + do { + /* + * Wait for data to drain, then flush again. + */ +#ifdef USE_TERMIO + tcsetattr(tin, TCSADRAIN, &tmp_tc); +#endif /* USE_TERMIO */ + old = ttyflush(SYNCHing|flushout); + } while (old < 0 || old > 1); + } + + old = prevmode; + prevmode = f&~MODE_FORCE; +#ifndef USE_TERMIO + sb = nttyb; + tc = ntc; + ltc = nltc; + lmode = olmode; +#else + tmp_tc = new_tc; +#endif + + if (f&MODE_ECHO) { +#ifndef USE_TERMIO + sb.sg_flags |= ECHO; +#else + tmp_tc.c_lflag |= ECHO; + tmp_tc.c_oflag |= ONLCR; + if (crlf) + tmp_tc.c_iflag |= ICRNL; +#endif + } else { +#ifndef USE_TERMIO + sb.sg_flags &= ~ECHO; +#else + tmp_tc.c_lflag &= ~ECHO; + tmp_tc.c_oflag &= ~ONLCR; +# ifdef notdef + if (crlf) + tmp_tc.c_iflag &= ~ICRNL; +# endif +#endif + } + + if ((f&MODE_FLOW) == 0) { +#ifndef USE_TERMIO + tc.t_startc = _POSIX_VDISABLE; + tc.t_stopc = _POSIX_VDISABLE; +#else + tmp_tc.c_iflag &= ~(IXOFF|IXON); /* Leave the IXANY bit alone */ + } else { + if (restartany < 0) { + tmp_tc.c_iflag |= IXOFF|IXON; /* Leave the IXANY bit alone */ + } else if (restartany > 0) { + tmp_tc.c_iflag |= IXOFF|IXON|IXANY; + } else { + tmp_tc.c_iflag |= IXOFF|IXON; + tmp_tc.c_iflag &= ~IXANY; + } +#endif + } + + if ((f&MODE_TRAPSIG) == 0) { +#ifndef USE_TERMIO + tc.t_intrc = _POSIX_VDISABLE; + tc.t_quitc = _POSIX_VDISABLE; + tc.t_eofc = _POSIX_VDISABLE; + ltc.t_suspc = _POSIX_VDISABLE; + ltc.t_dsuspc = _POSIX_VDISABLE; +#else + tmp_tc.c_lflag &= ~ISIG; +#endif + localchars = 0; + } else { +#ifdef USE_TERMIO + tmp_tc.c_lflag |= ISIG; +#endif + localchars = 1; + } + + if (f&MODE_EDIT) { +#ifndef USE_TERMIO + sb.sg_flags &= ~CBREAK; + sb.sg_flags |= CRMOD; +#else + tmp_tc.c_lflag |= ICANON; +#endif + } else { +#ifndef USE_TERMIO + sb.sg_flags |= CBREAK; + if (f&MODE_ECHO) + sb.sg_flags |= CRMOD; + else + sb.sg_flags &= ~CRMOD; +#else + tmp_tc.c_lflag &= ~ICANON; + tmp_tc.c_iflag &= ~ICRNL; + tmp_tc.c_cc[VMIN] = 1; + tmp_tc.c_cc[VTIME] = 0; +#endif + } + + if ((f&(MODE_EDIT|MODE_TRAPSIG)) == 0) { +#ifndef USE_TERMIO + ltc.t_lnextc = _POSIX_VDISABLE; +#else +# ifdef VLNEXT + tmp_tc.c_cc[VLNEXT] = (cc_t)(_POSIX_VDISABLE); +# endif +#endif + } + + if (f&MODE_SOFT_TAB) { +#ifndef USE_TERMIO + sb.sg_flags |= XTABS; +#else +# ifdef OXTABS + tmp_tc.c_oflag |= OXTABS; +# endif +# ifdef TABDLY + tmp_tc.c_oflag &= ~TABDLY; + tmp_tc.c_oflag |= TAB3; +# endif +#endif + } else { +#ifndef USE_TERMIO + sb.sg_flags &= ~XTABS; +#else +# ifdef OXTABS + tmp_tc.c_oflag &= ~OXTABS; +# endif +# ifdef TABDLY + tmp_tc.c_oflag &= ~TABDLY; +# endif +#endif + } + + if (f&MODE_LIT_ECHO) { +#ifndef USE_TERMIO + lmode &= ~LCTLECH; +#else +# ifdef ECHOCTL + tmp_tc.c_lflag &= ~ECHOCTL; +# endif +#endif + } else { +#ifndef USE_TERMIO + lmode |= LCTLECH; +#else +# ifdef ECHOCTL + tmp_tc.c_lflag |= ECHOCTL; +# endif +#endif + } + + if (f == -1) { + onoff = 0; + } else { +#ifndef USE_TERMIO + if (f & MODE_OUTBIN) + lmode |= LLITOUT; + else + lmode &= ~LLITOUT; + + if (f & MODE_INBIN) + lmode |= LPASS8; + else + lmode &= ~LPASS8; +#else + if (f & MODE_INBIN) + tmp_tc.c_iflag &= ~ISTRIP; + else + tmp_tc.c_iflag |= ISTRIP; + if (f & MODE_OUTBIN) { + tmp_tc.c_cflag &= ~(CSIZE|PARENB); + tmp_tc.c_cflag |= CS8; + tmp_tc.c_oflag &= ~OPOST; + } else { + tmp_tc.c_cflag &= ~(CSIZE|PARENB); + tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB); + tmp_tc.c_oflag |= OPOST; + } +#endif + onoff = 1; + } + + if (f != -1) { +#ifdef SIGTSTP + SIG_FUNC_RET susp(); +#endif /* SIGTSTP */ +#ifdef SIGINFO + SIG_FUNC_RET ayt(); +#endif + +#ifdef SIGTSTP + (void) signal(SIGTSTP, susp); +#endif /* SIGTSTP */ +#ifdef SIGINFO + (void) signal(SIGINFO, ayt); +#endif +#if defined(USE_TERMIO) && defined(NOKERNINFO) + tmp_tc.c_lflag |= NOKERNINFO; +#endif + /* + * We don't want to process ^Y here. It's just another + * character that we'll pass on to the back end. It has + * to process it because it will be processed when the + * user attempts to read it, not when we send it. + */ +#ifndef USE_TERMIO + ltc.t_dsuspc = _POSIX_VDISABLE; +#else +# ifdef VDSUSP + tmp_tc.c_cc[VDSUSP] = (cc_t)(_POSIX_VDISABLE); +# endif +#endif +#ifdef USE_TERMIO + /* + * If the VEOL character is already set, then use VEOL2, + * otherwise use VEOL. + */ + esc = (rlogin != _POSIX_VDISABLE) ? rlogin : escape; + if ((tmp_tc.c_cc[VEOL] != esc) +# ifdef VEOL2 + && (tmp_tc.c_cc[VEOL2] != esc) +# endif + ) { + if (tmp_tc.c_cc[VEOL] == (cc_t)(_POSIX_VDISABLE)) + tmp_tc.c_cc[VEOL] = esc; +# ifdef VEOL2 + else if (tmp_tc.c_cc[VEOL2] == (cc_t)(_POSIX_VDISABLE)) + tmp_tc.c_cc[VEOL2] = esc; +# endif + } +#else + if (tc.t_brkc == (cc_t)(_POSIX_VDISABLE)) + tc.t_brkc = esc; +#endif + } else { +#ifdef SIGINFO + SIG_FUNC_RET ayt_status(); + + (void) signal(SIGINFO, ayt_status); +#endif +#ifdef SIGTSTP + (void) signal(SIGTSTP, SIG_DFL); +# ifndef SOLARIS + (void) sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1))); +# else SOLARIS + (void) sigrelse(SIGTSTP); +# endif SOLARIS +#endif /* SIGTSTP */ +#ifndef USE_TERMIO + ltc = oltc; + tc = otc; + sb = ottyb; + lmode = olmode; +#else + tmp_tc = old_tc; +#endif + } +#ifndef USE_TERMIO + ioctl(tin, TIOCLSET, (char *)&lmode); + ioctl(tin, TIOCSLTC, (char *)<c); + ioctl(tin, TIOCSETC, (char *)&tc); + ioctl(tin, TIOCSETN, (char *)&sb); +#else + if (tcsetattr(tin, TCSADRAIN, &tmp_tc) < 0) + tcsetattr(tin, TCSANOW, &tmp_tc); +#endif + +#if (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) +# if !defined(sysV88) + ioctl(tin, FIONBIO, (char *)&onoff); + ioctl(tout, FIONBIO, (char *)&onoff); +# endif +#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */ +#if defined(TN3270) + if (noasynchtty == 0) { + ioctl(tin, FIOASYNC, (char *)&onoff); + } +#endif /* defined(TN3270) */ + +} + +/* + * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). + */ +#if B4800 != 4800 +#define DECODE_BAUD +#endif + +#ifdef DECODE_BAUD +#ifndef B7200 +#define B7200 B4800 +#endif + +#ifndef B14400 +#define B14400 B9600 +#endif + +#ifndef B19200 +# define B19200 B14400 +#endif + +#ifndef B28800 +#define B28800 B19200 +#endif + +#ifndef B38400 +# define B38400 B28800 +#endif + +#ifndef B57600 +#define B57600 B38400 +#endif + +#ifndef B76800 +#define B76800 B57600 +#endif + +#ifndef B115200 +#define B115200 B76800 +#endif + +#ifndef B230400 +#define B230400 B115200 +#endif + + +/* + * This code assumes that the values B0, B50, B75... + * are in ascending order. They do not have to be + * contiguous. + */ +struct termspeeds { + long speed; + long value; +} termspeeds[] = { + { 0, B0 }, { 50, B50 }, { 75, B75 }, + { 110, B110 }, { 134, B134 }, { 150, B150 }, + { 200, B200 }, { 300, B300 }, { 600, B600 }, + { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, + { 4800, B4800 }, { 7200, B7200 }, { 9600, B9600 }, + { 14400, B14400 }, { 19200, B19200 }, { 28800, B28800 }, + { 38400, B38400 }, { 57600, B57600 }, { 115200, B115200 }, + { 230400, B230400 }, { -1, B230400 } +}; +#endif /* DECODE_BAUD */ + + void +TerminalSpeeds(ispeed, ospeed) + long *ispeed; + long *ospeed; +{ +#ifdef DECODE_BAUD + register struct termspeeds *tp; +#endif /* DECODE_BAUD */ + register long in, out; + + out = cfgetospeed(&old_tc); + in = cfgetispeed(&old_tc); + if (in == 0) + in = out; + +#ifdef DECODE_BAUD + tp = termspeeds; + while ((tp->speed != -1) && (tp->value < in)) + tp++; + *ispeed = tp->speed; + + tp = termspeeds; + while ((tp->speed != -1) && (tp->value < out)) + tp++; + *ospeed = tp->speed; +#else /* DECODE_BAUD */ + *ispeed = in; + *ospeed = out; +#endif /* DECODE_BAUD */ +} + + int +TerminalWindowSize(rows, cols) + long *rows, *cols; +{ +#ifdef TIOCGWINSZ + struct winsize ws; + + if (ioctl(fileno(stdin), TIOCGWINSZ, (char *)&ws) >= 0) { + *rows = ws.ws_row; + *cols = ws.ws_col; + return 1; + } +#endif /* TIOCGWINSZ */ + return 0; +} + + int +NetClose(fd) + int fd; +{ + return close(fd); +} + + + void +NetNonblockingIO(fd, onoff) + int fd; + int onoff; +{ + ioctl(fd, FIONBIO, (char *)&onoff); +} + +#if defined(TN3270) + void +NetSigIO(fd, onoff) + int fd; + int onoff; +{ + ioctl(fd, FIOASYNC, (char *)&onoff); /* hear about input */ +} + + void +NetSetPgrp(fd) + int fd; +{ + int myPid; + + myPid = getpid(); + fcntl(fd, F_SETOWN, myPid); +} +#endif /*defined(TN3270)*/ + +/* + * Various signal handling routines. + */ + + /* ARGSUSED */ + SIG_FUNC_RET +deadpeer(sig) + int sig; +{ + setcommandmode(); + longjmp(peerdied, -1); +} + + /* ARGSUSED */ + SIG_FUNC_RET +intr(sig) + int sig; +{ + if (localchars) { + intp(); + return; + } + setcommandmode(); + longjmp(toplevel, -1); +} + + /* ARGSUSED */ + SIG_FUNC_RET +intr2(sig) + int sig; +{ + if (localchars) { +#ifdef KLUDGELINEMODE + if (kludgelinemode) + sendbrk(); + else +#endif + sendabort(); + return; + } +} + +#ifdef SIGTSTP + /* ARGSUSED */ + SIG_FUNC_RET +susp(sig) + int sig; +{ + if ((rlogin != _POSIX_VDISABLE) && rlogin_susp()) + return; + if (localchars) + sendsusp(); +} +#endif + +#ifdef SIGWINCH + /* ARGSUSED */ + SIG_FUNC_RET +sendwin(sig) + int sig; +{ + if (connected) { + sendnaws(); + } +} +#endif + +#ifdef SIGINFO + /* ARGSUSED */ + SIG_FUNC_RET +ayt(sig) + int sig; +{ + if (connected) + sendayt(); + else + ayt_status(); +} +#endif + + + void +sys_telnet_init() +{ + (void) signal(SIGINT, intr); + (void) signal(SIGQUIT, intr2); + (void) signal(SIGPIPE, deadpeer); +#ifdef SIGWINCH + (void) signal(SIGWINCH, sendwin); +#endif +#ifdef SIGTSTP + (void) signal(SIGTSTP, susp); +#endif +#ifdef SIGINFO + (void) signal(SIGINFO, ayt); +#endif + + setconnmode(0); + + NetNonblockingIO(net, 1); + +#if defined(TN3270) + if (noasynchnet == 0) { /* DBX can't handle! */ + NetSigIO(net, 1); + NetSetPgrp(net); + } +#endif /* defined(TN3270) */ + +#if defined(SO_OOBINLINE) + if (SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1) == -1) { + perror("SetSockOpt"); + } +#endif /* defined(SO_OOBINLINE) */ +} + +/* + * Process rings - + * + * This routine tries to fill up/empty our various rings. + * + * The parameter specifies whether this is a poll operation, + * or a block-until-something-happens operation. + * + * The return value is 1 if something happened, 0 if not. + */ + + int +process_rings(netin, netout, netex, ttyin, ttyout, poll) + int poll; /* If 0, then block until something to do */ +{ + register int c; + /* One wants to be a bit careful about setting returnValue + * to one, since a one implies we did some useful work, + * and therefore probably won't be called to block next + * time (TN3270 mode only). + */ + int returnValue = 0; + static struct timeval TimeValue = { 0 }; + + if (netout) { + FD_SET(net, &obits); + } + if (ttyout) { + FD_SET(tout, &obits); + } +#if defined(TN3270) + if (ttyin) { + FD_SET(tin, &ibits); + } +#else /* defined(TN3270) */ + if (ttyin) { + FD_SET(tin, &ibits); + } +#endif /* defined(TN3270) */ +#if defined(TN3270) + if (netin) { + FD_SET(net, &ibits); + } +# else /* !defined(TN3270) */ + if (netin) { + FD_SET(net, &ibits); + } +# endif /* !defined(TN3270) */ + if (netex) { + FD_SET(net, &xbits); + } + if ((c = select(16, &ibits, &obits, &xbits, + (poll == 0)? (struct timeval *)0 : &TimeValue)) < 0) { + if (c == -1) { + /* + * we can get EINTR if we are in line mode, + * and the user does an escape (TSTP), or + * some other signal generator. + */ + if (errno == EINTR) { + return 0; + } +# if defined(TN3270) + /* + * we can get EBADF if we were in transparent + * mode, and the transcom process died. + */ + if (errno == EBADF) { + /* + * zero the bits (even though kernel does it) + * to make sure we are selecting on the right + * ones. + */ + FD_ZERO(&ibits); + FD_ZERO(&obits); + FD_ZERO(&xbits); + return 0; + } +# endif /* defined(TN3270) */ + /* I don't like this, does it ever happen? */ + printf("sleep(5) from telnet, after select\r\n"); + sleep(5); + } + return 0; + } + + /* + * Any urgent data? + */ + if (FD_ISSET(net, &xbits)) { + FD_CLR(net, &xbits); + SYNCHing = 1; + (void) ttyflush(1); /* flush already enqueued data */ + } + + /* + * Something to read from the network... + */ + if (FD_ISSET(net, &ibits)) { + int canread; + + FD_CLR(net, &ibits); + canread = ring_empty_consecutive(&netiring); +#if !defined(SO_OOBINLINE) + /* + * In 4.2 (and some early 4.3) systems, the + * OOB indication and data handling in the kernel + * is such that if two separate TCP Urgent requests + * come in, one byte of TCP data will be overlaid. + * This is fatal for Telnet, but we try to live + * with it. + * + * In addition, in 4.2 (and...), a special protocol + * is needed to pick up the TCP Urgent data in + * the correct sequence. + * + * What we do is: if we think we are in urgent + * mode, we look to see if we are "at the mark". + * If we are, we do an OOB receive. If we run + * this twice, we will do the OOB receive twice, + * but the second will fail, since the second + * time we were "at the mark", but there wasn't + * any data there (the kernel doesn't reset + * "at the mark" until we do a normal read). + * Once we've read the OOB data, we go ahead + * and do normal reads. + * + * There is also another problem, which is that + * since the OOB byte we read doesn't put us + * out of OOB state, and since that byte is most + * likely the TELNET DM (data mark), we would + * stay in the TELNET SYNCH (SYNCHing) state. + * So, clocks to the rescue. If we've "just" + * received a DM, then we test for the + * presence of OOB data when the receive OOB + * fails (and AFTER we did the normal mode read + * to clear "at the mark"). + */ + if (SYNCHing) { + int atmark; + static int bogus_oob = 0, first = 1; + + ioctl(net, SIOCATMARK, (char *)&atmark); + if (atmark) { + c = recv(net, netiring.supply, canread, MSG_OOB); + if ((c == -1) && (errno == EINVAL)) { + c = recv(net, netiring.supply, canread, 0); + if (clocks.didnetreceive < clocks.gotDM) { + SYNCHing = stilloob(net); + } + } else if (first && c > 0) { + /* + * Bogosity check. Systems based on 4.2BSD + * do not return an error if you do a second + * recv(MSG_OOB). So, we do one. If it + * succeeds and returns exactly the same + * data, then assume that we are running + * on a broken system and set the bogus_oob + * flag. (If the data was different, then + * we probably got some valid new data, so + * increment the count...) + */ + int i; + i = recv(net, netiring.supply + c, canread - c, MSG_OOB); + if (i == c && + memcmp(netiring.supply, netiring.supply + c, i) == 0) { + bogus_oob = 1; + first = 0; + } else if (i < 0) { + bogus_oob = 0; + first = 0; + } else + c += i; + } + if (bogus_oob && c > 0) { + int i; + /* + * Bogosity. We have to do the read + * to clear the atmark to get out of + * an infinate loop. + */ + i = read(net, netiring.supply + c, canread - c); + if (i > 0) + c += i; + } + } else { + c = recv(net, netiring.supply, canread, 0); + } + } else { + c = recv(net, netiring.supply, canread, 0); + } + settimer(didnetreceive); +#else /* !defined(SO_OOBINLINE) */ + c = recv(net, (char *)netiring.supply, canread, 0); +#endif /* !defined(SO_OOBINLINE) */ + if (c < 0 && errno == EWOULDBLOCK) { + c = 0; + } else if (c <= 0) { + return -1; + } + if (netdata) { + Dump('<', netiring.supply, c); + } + if (c) + ring_supplied(&netiring, c); + returnValue = 1; + } + + /* + * Something to read from the tty... + */ + if (FD_ISSET(tin, &ibits)) { + FD_CLR(tin, &ibits); + c = TerminalRead(ttyiring.supply, ring_empty_consecutive(&ttyiring)); + if (c < 0 && errno == EIO) + c = 0; + if (c < 0 && errno == EWOULDBLOCK) { + c = 0; + } else { + /* EOF detection for line mode!!!! */ + if ((c == 0) && MODE_LOCAL_CHARS(globalmode) && isatty(tin)) { + /* must be an EOF... */ + *ttyiring.supply = termEofChar; + c = 1; + } + if (c <= 0) { + return -1; + } + if (termdata) { + Dump('<', ttyiring.supply, c); + } + ring_supplied(&ttyiring, c); + } + returnValue = 1; /* did something useful */ + } + + if (FD_ISSET(net, &obits)) { + FD_CLR(net, &obits); + returnValue |= netflush(); + } + if (FD_ISSET(tout, &obits)) { + FD_CLR(tout, &obits); + returnValue |= (ttyflush(SYNCHing|flushout) > 0); + } + + return returnValue; +} diff --git a/telnet.tproj/telnet.1 b/telnet.tproj/telnet.1 new file mode 100644 index 0000000..b996fea --- /dev/null +++ b/telnet.tproj/telnet.1 @@ -0,0 +1,1366 @@ +.\" Copyright (c) 1983, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)telnet.1 8.6 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt TELNET 1 +.Os BSD 4.2 +.Sh NAME +.Nm telnet +.Nd user interface to the +.Tn TELNET +protocol +.Sh SYNOPSIS +.Nm telnet +.Op Fl 8EFKLacdfrx +.Op Fl S Ar tos +.Op Fl X Ar authtype +.Op Fl e Ar escapechar +.Op Fl k Ar realm +.Op Fl l Ar user +.Op Fl n Ar tracefile +.Oo +.Ar host +.Op port +.Oc +.Sh DESCRIPTION +The +.Nm telnet +command +is used to communicate with another host using the +.Tn TELNET +protocol. +If +.Nm telnet +is invoked without the +.Ar host +argument, it enters command mode, +indicated by its prompt +.Pq Nm telnet\&> . +In this mode, it accepts and executes the commands listed below. +If it is invoked with arguments, it performs an +.Ic open +command with those arguments. +.Pp +Options: +.Bl -tag -width indent +.It Fl 8 +Specifies an 8-bit data path. This causes an attempt to +negotiate the +.Dv TELNET BINARY +option on both input and output. +.It Fl E +Stops any character from being recognized as an escape character. +.It Fl F +If Kerberos V5 authentication is being used, the +.Fl F +option allows the local credentials to be forwarded +to the remote system, including any credentials that +have already been forwarded into the local environment. +.It Fl K +Specifies no automatic login to the remote system. +.It Fl L +Specifies an 8-bit data path on output. This causes the +BINARY option to be negotiated on output. +.It Fl S Ar tos +Sets the IP type-of-service (TOS) option for the telnet +connection to the value +.Ar tos, +which can be a numeric TOS value +or, on systems that support it, a symbolic +TOS name found in the /etc/iptos file. +.It Fl X Ar atype +Disables the +.Ar atype +type of authentication. +.It Fl a +Attempt automatic login. +Currently, this sends the user name via the +.Ev USER +variable +of the +.Ev ENVIRON +option if supported by the remote system. +The name used is that of the current user as returned by +.Xr getlogin 2 +if it agrees with the current user ID, +otherwise it is the name associated with the user ID. +.It Fl c +Disables the reading of the user's +.Pa \&.telnetrc +file. (See the +.Ic toggle skiprc +command on this man page.) +.It Fl d +Sets the initial value of the +.Ic debug +toggle to +.Dv TRUE +.It Fl e Ar escape char +Sets the initial +.Nm +.Nm telnet +escape character to +.Ar escape char. +If +.Ar escape char +is omitted, then +there will be no escape character. +.It Fl f +If Kerberos V5 authentication is being used, the +.Fl f +option allows the local credentials to be forwarded to the remote system. +.ne 1i +.It Fl k Ar realm +If Kerberos authentication is being used, the +.Fl k +option requests that telnet obtain tickets for the remote host in +realm realm instead of the remote host's realm, as determined +by +.Xr krb_realmofhost 3 . +.It Fl l Ar user +When connecting to the remote system, if the remote system +understands the +.Ev ENVIRON +option, then +.Ar user +will be sent to the remote system as the value for the variable USER. +This option implies the +.Fl a +option. +This option may also be used with the +.Ic open +command. +.It Fl n Ar tracefile +Opens +.Ar tracefile +for recording trace information. +See the +.Ic set tracefile +command below. +.It Fl r +Specifies a user interface similar to +.Xr rlogin 1 . +In this +mode, the escape character is set to the tilde (~) character, +unless modified by the -e option. +.It Fl x +Turns on encryption of the data stream if possible. This +option is not available outside of the United States and +Canada. +.It Ar host +Indicates the official name, an alias, or the Internet address +of a remote host. +.It Ar port +Indicates a port number (address of an application). If a number is +not specified, the default +.Nm telnet +port is used. +.El +.Pp +When in rlogin mode, a line of the form ~. disconnects from the +remote host; ~ is the telnet escape character. +Similarly, the line ~^Z suspends the telnet session. +The line ~^] escapes to the normal telnet escape prompt. +.Pp +Once a connection has been opened, +.Nm telnet +will attempt to enable the +.Dv TELNET LINEMODE +option. +If this fails, then +.Nm telnet +will revert to one of two input modes: +either \*(Lqcharacter at a time\*(Rq +or \*(Lqold line by line\*(Rq +depending on what the remote system supports. +.Pp +When +.Dv LINEMODE +is enabled, character processing is done on the +local system, under the control of the remote system. When input +editing or character echoing is to be disabled, the remote system +will relay that information. The remote system will also relay +changes to any special characters that happen on the remote +system, so that they can take effect on the local system. +.Pp +In \*(Lqcharacter at a time\*(Rq mode, most +text typed is immediately sent to the remote host for processing. +.Pp +In \*(Lqold line by line\*(Rq mode, all text is echoed locally, +and (normally) only completed lines are sent to the remote host. +The \*(Lqlocal echo character\*(Rq (initially \*(Lq^E\*(Rq) may be used +to turn off and on the local echo +(this would mostly be used to enter passwords +without the password being echoed). +.Pp +If the +.Dv LINEMODE +option is enabled, or if the +.Ic localchars +toggle is +.Dv TRUE +(the default for \*(Lqold line by line\*(Lq; see below), +the user's +.Ic quit , +.Ic intr , +and +.Ic flush +characters are trapped locally, and sent as +.Tn TELNET +protocol sequences to the remote side. +If +.Dv LINEMODE +has ever been enabled, then the user's +.Ic susp +and +.Ic eof +are also sent as +.Tn TELNET +protocol sequences, +and +.Ic quit +is sent as a +.Dv TELNET ABORT +instead of +.Dv BREAK +There are options (see +.Ic toggle +.Ic autoflush +and +.Ic toggle +.Ic autosynch +below) +which cause this action to flush subsequent output to the terminal +(until the remote host acknowledges the +.Tn TELNET +sequence) and flush previous terminal input +(in the case of +.Ic quit +and +.Ic intr ) . +.Pp +While connected to a remote host, +.Nm telnet +command mode may be entered by typing the +.Nm telnet +\*(Lqescape character\*(Rq (initially \*(Lq^]\*(Rq). +When in command mode, the normal terminal editing conventions are available. +.Pp +The following +.Nm telnet +commands are available. +Only enough of each command to uniquely identify it need be typed +(this is also true for arguments to the +.Ic mode , +.Ic set , +.Ic toggle , +.Ic unset , +.Ic slc , +.Ic environ , +and +.Ic display +commands). +.Pp +.Bl -tag -width "mode type" +.It Ic auth Ar argument ... +The auth command manipulates the information sent through the +.Dv TELNET AUTHENTICATE +option. Valid arguments for the +auth command are as follows: +.Bl -tag -width "disable type" +.It Ic disable Ar type +Disables the specified type of authentication. To +obtain a list of available types, use the +.Ic auth disable \&? +command. +.It Ic enable Ar type +Enables the specified type of authentication. To +obtain a list of available types, use the +.Ic auth enable \&? +command. +.It Ic status +Lists the current status of the various types of +authentication. +.El +.It Ic close +Close a +.Tn TELNET +session and return to command mode. +.It Ic display Ar argument ... +Displays all, or some, of the +.Ic set +and +.Ic toggle +values (see below). +.It Ic encrypt Ar argument ... +The encrypt command manipulates the information sent through the +.Dv TELNET ENCRYPT +option. +.Pp +Note: Because of export controls, the +.Dv TELNET ENCRYPT +option is not supported outside of the United States and Canada. +.Pp +Valid arguments for the encrypt command are as follows: +.Bl -tag -width Ar +.It Ic disable Ar type Ic [input|output] +Disables the specified type of encryption. If you +omit the input and output, both input and output +are disabled. To obtain a list of available +types, use the +.Ic encrypt disable \&? +command. +.It Ic enable Ar type Ic [input|output] +Enables the specified type of encryption. If you +omit input and output, both input and output are +enabled. To obtain a list of available types, use the +.Ic encrypt enable \&? +command. +.It Ic input +This is the same as the +.Ic encrypt start input +command. +.It Ic -input +This is the same as the +.Ic encrypt stop input +command. +.It Ic output +This is the same as the +.Ic encrypt start output +command. +.It Ic -output +This is the same as the +.Ic encrypt stop output +command. +.It Ic start Ic [input|output] +Attempts to start encryption. If you omit +.Ic input +and +.Ic output, +both input and output are enabled. To +obtain a list of available types, use the +.Ic encrypt enable \&? +command. +.It Ic status +Lists the current status of encryption. +.It Ic stop Ic [input|output] +Stops encryption. If you omit input and output, +encryption is on both input and output. +.It Ic type Ar type +Sets the default type of encryption to be used +with later +.Ic encrypt start +or +.Ic encrypt stop +commands. +.El +.It Ic environ Ar arguments... +The +.Ic environ +command is used to manipulate the +the variables that my be sent through the +.Dv TELNET ENVIRON +option. +The initial set of variables is taken from the users +environment, with only the +.Ev DISPLAY +and +.Ev PRINTER +variables being exported by default. +The +.Ev USER +variable is also exported if the +.Fl a +or +.Fl l +options are used. +.br +Valid arguments for the +.Ic environ +command are: +.Bl -tag -width Fl +.It Ic define Ar variable value +Define the variable +.Ar variable +to have a value of +.Ar value. +Any variables defined by this command are automatically exported. +The +.Ar value +may be enclosed in single or double quotes so +that tabs and spaces may be included. +.It Ic undefine Ar variable +Remove +.Ar variable +from the list of environment variables. +.It Ic export Ar variable +Mark the variable +.Ar variable +to be exported to the remote side. +.It Ic unexport Ar variable +Mark the variable +.Ar variable +to not be exported unless +explicitly asked for by the remote side. +.It Ic list +List the current set of environment variables. +Those marked with a +.Cm * +will be sent automatically, +other variables will only be sent if explicitly requested. +.It Ic \&? +Prints out help information for the +.Ic environ +command. +.El +.It Ic logout +Sends the +.Dv TELNET LOGOUT +option to the remote side. +This command is similar to a +.Ic close +command; however, if the remote side does not support the +.Dv LOGOUT +option, nothing happens. +If, however, the remote side does support the +.Dv LOGOUT +option, this command should cause the remote side to close the +.Tn TELNET +connection. +If the remote side also supports the concept of +suspending a user's session for later reattachment, +the logout argument indicates that you +should terminate the session immediately. +.It Ic mode Ar type +.Ar Type +is one of several options, depending on the state of the +.Tn TELNET +session. +The remote host is asked for permission to go into the requested mode. +If the remote host is capable of entering that mode, the requested +mode will be entered. +.Bl -tag -width Ar +.It Ic character +Disable the +.Dv TELNET LINEMODE +option, or, if the remote side does not understand the +.Dv LINEMODE +option, then enter \*(Lqcharacter at a time\*(Lq mode. +.It Ic line +Enable the +.Dv TELNET LINEMODE +option, or, if the remote side does not understand the +.Dv LINEMODE +option, then attempt to enter \*(Lqold-line-by-line\*(Lq mode. +.It Ic isig Pq Ic \-isig +Attempt to enable (disable) the +.Dv TRAPSIG +mode of the +.Dv LINEMODE +option. +This requires that the +.Dv LINEMODE +option be enabled. +.It Ic edit Pq Ic \-edit +Attempt to enable (disable) the +.Dv EDIT +mode of the +.Dv LINEMODE +option. +This requires that the +.Dv LINEMODE +option be enabled. +.It Ic softtabs Pq Ic \-softtabs +Attempt to enable (disable) the +.Dv SOFT_TAB +mode of the +.Dv LINEMODE +option. +This requires that the +.Dv LINEMODE +option be enabled. +.ne 1i +.It Ic litecho Pq Ic \-litecho +Attempt to enable (disable) the +.Dv LIT_ECHO +mode of the +.Dv LINEMODE +option. +This requires that the +.Dv LINEMODE +option be enabled. +.It Ic \&? +Prints out help information for the +.Ic mode +command. +.El +.It Xo +.Ic open Ar host +.Oo Op Fl l +.Ar user +.Oc Ns Oo Fl +.Ar port Oc +.Xc +Open a connection to the named host. +If no port number +is specified, +.Nm telnet +will attempt to contact a +.Tn TELNET +server at the default port. +The host specification may be either a host name (see +.Xr hosts 5 ) +or an Internet address specified in the \*(Lqdot notation\*(Rq (see +.Xr inet 3 ) . +The +.Op Fl l +option may be used to specify the user name +to be passed to the remote system via the +.Ev ENVIRON +option. +When connecting to a non-standard port, +.Nm telnet +omits any automatic initiation of +.Tn TELNET +options. When the port number is preceded by a minus sign, +the initial option negotiation is done. +After establishing a connection, the file +.Pa \&.telnetrc +in the +users home directory is opened. Lines beginning with a # are +comment lines. Blank lines are ignored. Lines that begin +without white space are the start of a machine entry. The +first thing on the line is the name of the machine that is +being connected to. The rest of the line, and successive +lines that begin with white space are assumed to be +.Nm telnet +commands and are processed as if they had been typed +in manually to the +.Nm telnet +command prompt. +.It Ic quit +Close any open +.Tn TELNET +session and exit +.Nm telnet . +An end of file (in command mode) will also close a session and exit. +.It Ic send Ar arguments +Sends one or more special character sequences to the remote host. +The following are the arguments which may be specified +(more than one argument may be specified at a time): +.Pp +.Bl -tag -width escape +.It Ic abort +Sends the +.Dv TELNET ABORT +(Abort +processes) +sequence. +.It Ic ao +Sends the +.Dv TELNET AO +(Abort Output) sequence, which should cause the remote system to flush +all output +.Em from +the remote system +.Em to +the user's terminal. +.It Ic ayt +Sends the +.Dv TELNET AYT +(Are You There) +sequence, to which the remote system may or may not choose to respond. +.It Ic brk +Sends the +.Dv TELNET BRK +(Break) sequence, which may have significance to the remote +system. +.It Ic ec +Sends the +.Dv TELNET EC +(Erase Character) +sequence, which should cause the remote system to erase the last character +entered. +.It Ic el +Sends the +.Dv TELNET EL +(Erase Line) +sequence, which should cause the remote system to erase the line currently +being entered. +.It Ic eof +Sends the +.Dv TELNET EOF +(End Of File) +sequence. +.It Ic eor +Sends the +.Dv TELNET EOR +(End of Record) +sequence. +.It Ic escape +Sends the current +.Nm telnet +escape character (initially \*(Lq^\*(Rq). +.It Ic ga +Sends the +.Dv TELNET GA +(Go Ahead) +sequence, which likely has no significance to the remote system. +.It Ic getstatus +If the remote side supports the +.Dv TELNET STATUS +command, +.Ic getstatus +will send the subnegotiation to request that the server send +its current option status. +.ne 1i +.It Ic ip +Sends the +.Dv TELNET IP +(Interrupt Process) sequence, which should cause the remote +system to abort the currently running process. +.It Ic nop +Sends the +.Dv TELNET NOP +(No OPeration) +sequence. +.It Ic susp +Sends the +.Dv TELNET SUSP +(SUSPend process) +sequence. +.It Ic synch +Sends the +.Dv TELNET SYNCH +sequence. +This sequence causes the remote system to discard all previously typed +(but not yet read) input. +This sequence is sent as +.Tn TCP +urgent +data (and may not work if the remote system is a +.Bx 4.2 +system -- if +it doesn't work, a lower case \*(Lqr\*(Rq may be echoed on the terminal). +.It Ic do Ar cmd +.It Ic dont Ar cmd +.It Ic will Ar cmd +.It Ic wont Ar cmd +Sends the +.Dv TELNET DO +.Ar cmd +sequence. +.Ar Cmd +can be either a decimal number between 0 and 255, +or a symbolic name for a specific +.Dv TELNET +command. +.Ar Cmd +can also be either +.Ic help +or +.Ic \&? +to print out help information, including +a list of known symbolic names. +.It Ic \&? +Prints out help information for the +.Ic send +command. +.El +.It Ic set Ar argument value +.It Ic unset Ar argument value +The +.Ic set +command will set any one of a number of +.Nm telnet +variables to a specific value or to +.Dv TRUE . +The special value +.Ic off +turns off the function associated with +the variable, this is equivalent to using the +.Ic unset +command. +The +.Ic unset +command will disable or set to +.Dv FALSE +any of the specified functions. +The values of variables may be interrogated with the +.Ic display +command. +The variables which may be set or unset, but not toggled, are +listed here. In addition, any of the variables for the +.Ic toggle +command may be explicitly set or unset using +the +.Ic set +and +.Ic unset +commands. +.Bl -tag -width escape +.It Ic ayt +If +.Tn TELNET +is in localchars mode, or +.Dv LINEMODE +is enabled, and the status character is typed, a +.Dv TELNET AYT +sequence (see +.Ic send ayt +preceding) is sent to the +remote host. The initial value for the "Are You There" +character is the terminal's status character. +.It Ic echo +This is the value (initially \*(Lq^E\*(Rq) which, when in +\*(Lqline by line\*(Rq mode, toggles between doing local echoing +of entered characters (for normal processing), and suppressing +echoing of entered characters (for entering, say, a password). +.It Ic eof +If +.Nm telnet +is operating in +.Dv LINEMODE +or \*(Lqold line by line\*(Rq mode, entering this character +as the first character on a line will cause this character to be +sent to the remote system. +The initial value of the eof character is taken to be the terminal's +.Ic eof +character. +.It Ic erase +If +.Nm telnet +is in +.Ic localchars +mode (see +.Ic toggle +.Ic localchars +below), +.Sy and +if +.Nm telnet +is operating in \*(Lqcharacter at a time\*(Rq mode, then when this +character is typed, a +.Dv TELNET EC +sequence (see +.Ic send +.Ic ec +above) +is sent to the remote system. +The initial value for the erase character is taken to be +the terminal's +.Ic erase +character. +.It Ic escape +This is the +.Nm telnet +escape character (initially \*(Lq^[\*(Rq) which causes entry +into +.Nm telnet +command mode (when connected to a remote system). +.It Ic flushoutput +If +.Nm telnet +is in +.Ic localchars +mode (see +.Ic toggle +.Ic localchars +below) +and the +.Ic flushoutput +character is typed, a +.Dv TELNET AO +sequence (see +.Ic send +.Ic ao +above) +is sent to the remote host. +The initial value for the flush character is taken to be +the terminal's +.Ic flush +character. +.It Ic forw1 +.It Ic forw2 +If +.Tn TELNET +is operating in +.Dv LINEMODE , +these are the +characters that, when typed, cause partial lines to be +forwarded to the remote system. The initial value for +the forwarding characters are taken from the terminal's +eol and eol2 characters. +.It Ic interrupt +If +.Nm telnet +is in +.Ic localchars +mode (see +.Ic toggle +.Ic localchars +below) +and the +.Ic interrupt +character is typed, a +.Dv TELNET IP +sequence (see +.Ic send +.Ic ip +above) +is sent to the remote host. +The initial value for the interrupt character is taken to be +the terminal's +.Ic intr +character. +.It Ic kill +If +.Nm telnet +is in +.Ic localchars +mode (see +.Ic toggle +.Ic localchars +below), +.Ic and +if +.Nm telnet +is operating in \*(Lqcharacter at a time\*(Rq mode, then when this +character is typed, a +.Dv TELNET EL +sequence (see +.Ic send +.Ic el +above) +is sent to the remote system. +The initial value for the kill character is taken to be +the terminal's +.Ic kill +character. +.It Ic lnext +If +.Nm telnet +is operating in +.Dv LINEMODE +or \*(Lqold line by line\*(Lq mode, then this character is taken to +be the terminal's +.Ic lnext +character. +The initial value for the lnext character is taken to be +the terminal's +.Ic lnext +character. +.It Ic quit +If +.Nm telnet +is in +.Ic localchars +mode (see +.Ic toggle +.Ic localchars +below) +and the +.Ic quit +character is typed, a +.Dv TELNET BRK +sequence (see +.Ic send +.Ic brk +above) +is sent to the remote host. +The initial value for the quit character is taken to be +the terminal's +.Ic quit +character. +.It Ic reprint +If +.Nm telnet +is operating in +.Dv LINEMODE +or \*(Lqold line by line\*(Lq mode, then this character is taken to +be the terminal's +.Ic reprint +character. +The initial value for the reprint character is taken to be +the terminal's +.Ic reprint +character. +.It Ic rlogin +This is the rlogin escape character. +If set, the normal +.Tn TELNET +escape character is ignored unless it is +preceded by this character at the beginning of a line. +This character, at the beginning of a line followed by +a "." closes the connection; when followed by a ^Z it +suspends the telnet command. The initial state is to +disable the rlogin escape character. +.It Ic start +If the +.Dv TELNET TOGGLE-FLOW-CONTROL +option has been enabled, +then this character is taken to +be the terminal's +.Ic start +character. +The initial value for the kill character is taken to be +the terminal's +.Ic start +character. +.It Ic stop +If the +.Dv TELNET TOGGLE-FLOW-CONTROL +option has been enabled, +then this character is taken to +be the terminal's +.Ic stop +character. +The initial value for the kill character is taken to be +the terminal's +.Ic stop +character. +.It Ic susp +If +.Nm telnet +is in +.Ic localchars +mode, or +.Dv LINEMODE +is enabled, and the +.Ic suspend +character is typed, a +.Dv TELNET SUSP +sequence (see +.Ic send +.Ic susp +above) +is sent to the remote host. +The initial value for the suspend character is taken to be +the terminal's +.Ic suspend +character. +.ne 1i +.It Ic tracefile +This is the file to which the output, caused by +.Ic netdata +or +.Ic option +tracing being +.Dv TRUE , +will be written. If it is set to +.Dq Fl , +then tracing information will be written to standard output (the default). +.It Ic worderase +If +.Nm telnet +is operating in +.Dv LINEMODE +or \*(Lqold line by line\*(Lq mode, then this character is taken to +be the terminal's +.Ic worderase +character. +The initial value for the worderase character is taken to be +the terminal's +.Ic worderase +character. +.It Ic \&? +Displays the legal +.Ic set +.Pq Ic unset +commands. +.El +.It Ic slc Ar state +The +.Ic slc +command (Set Local Characters) is used to set +or change the state of the the special +characters when the +.Dv TELNET LINEMODE +option has +been enabled. Special characters are characters that get +mapped to +.Tn TELNET +commands sequences (like +.Ic ip +or +.Ic quit ) +or line editing characters (like +.Ic erase +and +.Ic kill ) . +By default, the local special characters are exported. +.Bl -tag -width Fl +.It Ic check +Verify the current settings for the current special characters. +The remote side is requested to send all the current special +character settings, and if there are any discrepancies with +the local side, the local side will switch to the remote value. +.It Ic export +Switch to the local defaults for the special characters. The +local default characters are those of the local terminal at +the time when +.Nm telnet +was started. +.It Ic import +Switch to the remote defaults for the special characters. +The remote default characters are those of the remote system +at the time when the +.Tn TELNET +connection was established. +.It Ic \&? +Prints out help information for the +.Ic slc +command. +.El +.It Ic status +Show the current status of +.Nm telnet . +This includes the peer one is connected to, as well +as the current mode. +.It Ic toggle Ar arguments ... +Toggle (between +.Dv TRUE +and +.Dv FALSE ) +various flags that control how +.Nm telnet +responds to events. +These flags may be set explicitly to +.Dv TRUE +or +.Dv FALSE +using the +.Ic set +and +.Ic unset +commands listed above. +More than one argument may be specified. +The state of these flags may be interrogated with the +.Ic display +command. +Valid arguments are: +.Bl -tag -width Ar +.It Ic authdebug +Turns on debugging information for the authentication code. +.It Ic autoflush +If +.Ic autoflush +and +.Ic localchars +are both +.Dv TRUE , +then when the +.Ic ao , +or +.Ic quit +characters are recognized (and transformed into +.Tn TELNET +sequences; see +.Ic set +above for details), +.Nm telnet +refuses to display any data on the user's terminal +until the remote system acknowledges (via a +.Dv TELNET TIMING MARK +option) +that it has processed those +.Tn TELNET +sequences. +The initial value for this toggle is +.Dv TRUE +if the terminal user had not +done an "stty noflsh", otherwise +.Dv FALSE +(see +.Xr stty 1 ) . +.It Ic autodecrypt +When the +.Dv TELNET ENCRYPT +option is negotiated, by +default the actual encryption (decryption) of the data +stream does not start automatically. The autoencrypt +(autodecrypt) command states that encryption of the +output (input) stream should be enabled as soon as +possible. +.sp +.Pp +Note: Because of export controls, the +.Dv TELNET ENCRYPT +option is not supported outside the United States and Canada. +.It Ic autologin +If the remote side supports the +.Dv TELNET AUTHENTICATION +option +.Tn TELNET +attempts to use it to perform automatic authentication. If the +.Dv AUTHENTICATION +option is not supported, the user's login +name are propagated through the +.Dv TELNET ENVIRON +option. +This command is the same as specifying +.Ar a +option on the +.Ic open +command. +.It Ic autosynch +If +.Ic autosynch +and +.Ic localchars +are both +.Dv TRUE , +then when either the +.Ic intr +or +.Ic quit +characters is typed (see +.Ic set +above for descriptions of the +.Ic intr +and +.Ic quit +characters), the resulting +.Tn TELNET +sequence sent is followed by the +.Dv TELNET SYNCH +sequence. +This procedure +.Ic should +cause the remote system to begin throwing away all previously +typed input until both of the +.Tn TELNET +sequences have been read and acted upon. +The initial value of this toggle is +.Dv FALSE . +.It Ic binary +Enable or disable the +.Dv TELNET BINARY +option on both input and output. +.It Ic inbinary +Enable or disable the +.Dv TELNET BINARY +option on input. +.It Ic outbinary +Enable or disable the +.Dv TELNET BINARY +option on output. +.It Ic crlf +If this is +.Dv TRUE , +then carriage returns will be sent as +.Li . +If this is +.Dv FALSE , +then carriage returns will be send as +.Li . +The initial value for this toggle is +.Dv FALSE . +.It Ic crmod +Toggle carriage return mode. +When this mode is enabled, most carriage return characters received from +the remote host will be mapped into a carriage return followed by +a line feed. +This mode does not affect those characters typed by the user, only +those received from the remote host. +This mode is not very useful unless the remote host +only sends carriage return, but never line feed. +The initial value for this toggle is +.Dv FALSE . +.It Ic debug +Toggles socket level debugging (useful only to the +.Ic super user ) . +The initial value for this toggle is +.Dv FALSE . +.It Ic encdebug +Turns on debugging information for the encryption code. +.It Ic localchars +If this is +.Dv TRUE , +then the +.Ic flush , +.Ic interrupt , +.Ic quit , +.Ic erase , +and +.Ic kill +characters (see +.Ic set +above) are recognized locally, and transformed into (hopefully) appropriate +.Tn TELNET +control sequences +(respectively +.Ic ao , +.Ic ip , +.Ic brk , +.Ic ec , +and +.Ic el ; +see +.Ic send +above). +The initial value for this toggle is +.Dv TRUE +in \*(Lqold line by line\*(Rq mode, +and +.Dv FALSE +in \*(Lqcharacter at a time\*(Rq mode. +When the +.Dv LINEMODE +option is enabled, the value of +.Ic localchars +is ignored, and assumed to always be +.Dv TRUE . +If +.Dv LINEMODE +has ever been enabled, then +.Ic quit +is sent as +.Ic abort , +and +.Ic eof and +.B suspend +are sent as +.Ic eof and +.Ic susp , +see +.Ic send +above). +.It Ic netdata +Toggles the display of all network data (in hexadecimal format). +The initial value for this toggle is +.Dv FALSE . +.It Ic options +Toggles the display of some internal +.Nm telnet +protocol processing (having to do with +.Tn TELNET +options). +The initial value for this toggle is +.Dv FALSE . +.ne 1i +.It Ic prettydump +When the +.Ic netdata +toggle is enabled, if +.Ic prettydump +is enabled the output from the +.Ic netdata +command will be formatted in a more user readable format. +Spaces are put between each character in the output, and the +beginning of any +.Tn TELNET +escape sequence is preceded by a '*' to aid in locating them. +.It Ic skiprc +When the skiprc toggle is +.Dv TRUE , +.Tn TELNET +skips the reading of the +.Pa \&.telnetrc +file in the users home +directory when connections are opened. The initial +value for this toggle is +.Dv FALSE. +.It Ic termdata +Toggles the display of all terminal data (in hexadecimal format). +The initial value for this toggle is +.Dv FALSE . +.It Ic verbose_encrypt +When the +.Ic verbose_encrypt +toggle is +.Dv TRUE , +.Tn TELNET +prints out a message each time encryption is enabled or +disabled. The initial value for this toggle is +.Dv FALSE. +Note: Because of export controls, data encryption +is not supported outside of the United States and Canada. +.It Ic \&? +Displays the legal +.Ic toggle +commands. +.El +.It Ic z +Suspend +.Nm telnet . +This command only works when the user is using the +.Xr csh 1 . +.It Ic \&! Op Ar command +Execute a single command in a subshell on the local +system. If +.Ic command +is omitted, then an interactive +subshell is invoked. +.It Ic \&? Op Ar command +Get help. With no arguments, +.Nm telnet +prints a help summary. +If a command is specified, +.Nm telnet +will print the help information for just that command. +.El +.Sh ENVIRONMENT +.Nm Telnet +uses at least the +.Ev HOME , +.Ev SHELL , +.Ev DISPLAY , +and +.Ev TERM +environment variables. +Other environment variables may be propagated +to the other side via the +.Dv TELNET ENVIRON +option. +.Sh FILES +.Bl -tag -width ~/.telnetrc -compact +.It Pa ~/.telnetrc +user customized telnet startup values +.El +.Sh HISTORY +The +.Nm Telnet +command appeared in +.Bx 4.2 . +.Sh NOTES +.Pp +On some remote systems, echo has to be turned off manually when in +\*(Lqold line by line\*(Rq mode. +.Pp +In \*(Lqold line by line\*(Rq mode or +.Dv LINEMODE +the terminal's +.Ic eof +character is only recognized (and sent to the remote system) +when it is the first character on a line. diff --git a/telnet.tproj/telnet.c b/telnet.tproj/telnet.c new file mode 100644 index 0000000..e1a974f --- /dev/null +++ b/telnet.tproj/telnet.c @@ -0,0 +1,2673 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)telnet.c 8.4 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include + +#if defined(unix) || defined(__APPLE__) +#include +/* By the way, we need to include curses.h before telnet.h since, + * among other things, telnet.h #defines 'DO', which is a variable + * declared in curses.h. + */ +#endif /* defined(unix) || defined(__APPLE__) */ + +#include + +#include + +#include "ring.h" + +#include "defines.h" +#include "externs.h" +#include "types.h" +#include "general.h" + + +#define strip(x) ((my_want_state_is_wont(TELOPT_BINARY)) ? ((x)&0x7f) : (x)) + +static unsigned char subbuffer[SUBBUFSIZE], + *subpointer, *subend; /* buffer for sub-options */ +#define SB_CLEAR() subpointer = subbuffer; +#define SB_TERM() { subend = subpointer; SB_CLEAR(); } +#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ + *subpointer++ = (c); \ + } + +#define SB_GET() ((*subpointer++)&0xff) +#define SB_PEEK() ((*subpointer)&0xff) +#define SB_EOF() (subpointer >= subend) +#define SB_LEN() (subend - subpointer) + +char options[256]; /* The combined options */ +char do_dont_resp[256]; +char will_wont_resp[256]; + +int + eight = 0, + autologin = 0, /* Autologin anyone? */ + skiprc = 0, + connected, + showoptions, + In3270, /* Are we in 3270 mode? */ + ISend, /* trying to send network data in */ + debug = 0, + crmod, + netdata, /* Print out network data flow */ + crlf, /* Should '\r' be mapped to (or )? */ +#if defined(TN3270) + noasynchtty = 0,/* User specified "-noasynch" on command line */ + noasynchnet = 0,/* User specified "-noasynch" on command line */ + askedSGA = 0, /* We have talked about suppress go ahead */ +#endif /* defined(TN3270) */ + telnetport, + SYNCHing, /* we are in TELNET SYNCH mode */ + flushout, /* flush output */ + autoflush = 0, /* flush output when interrupting? */ + autosynch, /* send interrupt characters with SYNCH? */ + localflow, /* we handle flow control locally */ + restartany, /* if flow control enabled, restart on any character */ + localchars, /* we recognize interrupt/quit */ + donelclchars, /* the user has set "localchars" */ + donebinarytoggle, /* the user has put us in binary */ + dontlecho, /* do we suppress local echoing right now? */ + globalmode; + +char *prompt = 0; + +cc_t escape; +cc_t rlogin; +#ifdef KLUDGELINEMODE +cc_t echoc; +#endif + +/* + * Telnet receiver states for fsm + */ +#define TS_DATA 0 +#define TS_IAC 1 +#define TS_WILL 2 +#define TS_WONT 3 +#define TS_DO 4 +#define TS_DONT 5 +#define TS_CR 6 +#define TS_SB 7 /* sub-option collection */ +#define TS_SE 8 /* looking for sub-option end */ + +static int telrcv_state; +#ifdef OLD_ENVIRON +unsigned char telopt_environ = TELOPT_NEW_ENVIRON; +#else +# define telopt_environ TELOPT_NEW_ENVIRON +#endif + +jmp_buf toplevel = { 0 }; +jmp_buf peerdied; + +int flushline; +int linemode; + +#ifdef KLUDGELINEMODE +int kludgelinemode = 1; +#endif + +/* + * The following are some clocks used to decide how to interpret + * the relationship between various variables. + */ + +Clocks clocks; + +#ifdef notdef +Modelist modelist[] = { + { "telnet command mode", COMMAND_LINE }, + { "character-at-a-time mode", 0 }, + { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS }, + { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS }, + { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS }, + { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS }, + { "3270 mode", 0 }, +}; +#endif + + +/* + * Initialize telnet environment. + */ + + void +init_telnet() +{ + env_init(); + + SB_CLEAR(); + ClearArray(options); + + connected = In3270 = ISend = localflow = donebinarytoggle = 0; +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_connect(connected); +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ + restartany = -1; + + SYNCHing = 0; + + /* Don't change NetTrace */ + + escape = CONTROL(']'); + rlogin = _POSIX_VDISABLE; +#ifdef KLUDGELINEMODE + echoc = CONTROL('E'); +#endif + + flushline = 1; + telrcv_state = TS_DATA; +} + + +#ifdef notdef +#include + + /*VARARGS*/ + static void +printring(va_alist) + va_dcl +{ + va_list ap; + char buffer[100]; /* where things go */ + char *ptr; + char *format; + char *string; + Ring *ring; + int i; + + va_start(ap); + + ring = va_arg(ap, Ring *); + format = va_arg(ap, char *); + ptr = buffer; + + while ((i = *format++) != 0) { + if (i == '%') { + i = *format++; + switch (i) { + case 'c': + *ptr++ = va_arg(ap, int); + break; + case 's': + string = va_arg(ap, char *); + ring_supply_data(ring, buffer, ptr-buffer); + ring_supply_data(ring, string, strlen(string)); + ptr = buffer; + break; + case 0: + ExitString("printring: trailing %%.\n", 1); + /*NOTREACHED*/ + default: + ExitString("printring: unknown format character.\n", 1); + /*NOTREACHED*/ + } + } else { + *ptr++ = i; + } + } + ring_supply_data(ring, buffer, ptr-buffer); +} +#endif + +/* + * These routines are in charge of sending option negotiations + * to the other side. + * + * The basic idea is that we send the negotiation if either side + * is in disagreement as to what the current state should be. + */ + + void +send_do(c, init) + register int c, init; +{ + if (init) { + if (((do_dont_resp[c] == 0) && my_state_is_do(c)) || + my_want_state_is_do(c)) + return; + set_my_want_state_do(c); + do_dont_resp[c]++; + } + NET2ADD(IAC, DO); + NETADD(c); + printoption("SENT", DO, c); +} + + void +send_dont(c, init) + register int c, init; +{ + if (init) { + if (((do_dont_resp[c] == 0) && my_state_is_dont(c)) || + my_want_state_is_dont(c)) + return; + set_my_want_state_dont(c); + do_dont_resp[c]++; + } + NET2ADD(IAC, DONT); + NETADD(c); + printoption("SENT", DONT, c); +} + + void +send_will(c, init) + register int c, init; +{ + if (init) { + if (((will_wont_resp[c] == 0) && my_state_is_will(c)) || + my_want_state_is_will(c)) + return; + set_my_want_state_will(c); + will_wont_resp[c]++; + } + NET2ADD(IAC, WILL); + NETADD(c); + printoption("SENT", WILL, c); +} + + void +send_wont(c, init) + register int c, init; +{ + if (init) { + if (((will_wont_resp[c] == 0) && my_state_is_wont(c)) || + my_want_state_is_wont(c)) + return; + set_my_want_state_wont(c); + will_wont_resp[c]++; + } + NET2ADD(IAC, WONT); + NETADD(c); + printoption("SENT", WONT, c); +} + + + void +willoption(option) + int option; +{ + int new_state_ok = 0; + + if (do_dont_resp[option]) { + --do_dont_resp[option]; + if (do_dont_resp[option] && my_state_is_do(option)) + --do_dont_resp[option]; + } + + if ((do_dont_resp[option] == 0) && my_want_state_is_dont(option)) { + + switch (option) { + + case TELOPT_ECHO: +# if defined(TN3270) + /* + * The following is a pain in the rear-end. + * Various IBM servers (some versions of Wiscnet, + * possibly Fibronics/Spartacus, and who knows who + * else) will NOT allow us to send "DO SGA" too early + * in the setup proceedings. On the other hand, + * 4.2 servers (telnetd) won't set SGA correctly. + * So, we are stuck. Empirically (but, based on + * a VERY small sample), the IBM servers don't send + * out anything about ECHO, so we postpone our sending + * "DO SGA" until we see "WILL ECHO" (which 4.2 servers + * DO send). + */ + { + if (askedSGA == 0) { + askedSGA = 1; + if (my_want_state_is_dont(TELOPT_SGA)) + send_do(TELOPT_SGA, 1); + } + } + /* Fall through */ + case TELOPT_EOR: +#endif /* defined(TN3270) */ + case TELOPT_BINARY: + case TELOPT_SGA: + settimer(modenegotiated); + /* FALL THROUGH */ + case TELOPT_STATUS: +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: +#endif +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: +#endif /* ENCRYPTION */ + new_state_ok = 1; + break; + + case TELOPT_TM: + if (flushout) + flushout = 0; + /* + * Special case for TM. If we get back a WILL, + * pretend we got back a WONT. + */ + set_my_want_state_dont(option); + set_my_state_dont(option); + return; /* Never reply to TM will's/wont's */ + + case TELOPT_LINEMODE: + default: + break; + } + + if (new_state_ok) { + set_my_want_state_do(option); + send_do(option, 0); + setconnmode(0); /* possibly set new tty mode */ + } else { + do_dont_resp[option]++; + send_dont(option, 0); + } + } + set_my_state_do(option); +#ifdef ENCRYPTION + if (option == TELOPT_ENCRYPT) + encrypt_send_support(); +#endif /* ENCRYPTION */ +} + + void +wontoption(option) + int option; +{ + if (do_dont_resp[option]) { + --do_dont_resp[option]; + if (do_dont_resp[option] && my_state_is_dont(option)) + --do_dont_resp[option]; + } + + if ((do_dont_resp[option] == 0) && my_want_state_is_do(option)) { + + switch (option) { + +#ifdef KLUDGELINEMODE + case TELOPT_SGA: + if (!kludgelinemode) + break; + /* FALL THROUGH */ +#endif + case TELOPT_ECHO: + settimer(modenegotiated); + break; + + case TELOPT_TM: + if (flushout) + flushout = 0; + set_my_want_state_dont(option); + set_my_state_dont(option); + return; /* Never reply to TM will's/wont's */ + + default: + break; + } + set_my_want_state_dont(option); + if (my_state_is_do(option)) + send_dont(option, 0); + setconnmode(0); /* Set new tty mode */ + } else if (option == TELOPT_TM) { + /* + * Special case for TM. + */ + if (flushout) + flushout = 0; + set_my_want_state_dont(option); + } + set_my_state_dont(option); +} + + static void +dooption(option) + int option; +{ + int new_state_ok = 0; + + if (will_wont_resp[option]) { + --will_wont_resp[option]; + if (will_wont_resp[option] && my_state_is_will(option)) + --will_wont_resp[option]; + } + + if (will_wont_resp[option] == 0) { + if (my_want_state_is_wont(option)) { + + switch (option) { + + case TELOPT_TM: + /* + * Special case for TM. We send a WILL, but pretend + * we sent WONT. + */ + send_will(option, 0); + set_my_want_state_wont(TELOPT_TM); + set_my_state_wont(TELOPT_TM); + return; + +# if defined(TN3270) + case TELOPT_EOR: /* end of record */ +# endif /* defined(TN3270) */ + case TELOPT_BINARY: /* binary mode */ + case TELOPT_NAWS: /* window size */ + case TELOPT_TSPEED: /* terminal speed */ + case TELOPT_LFLOW: /* local flow control */ + case TELOPT_TTYPE: /* terminal type option */ + case TELOPT_SGA: /* no big deal */ +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: /* encryption variable option */ +#endif /* ENCRYPTION */ + new_state_ok = 1; + break; + + case TELOPT_NEW_ENVIRON: /* New environment variable option */ +#ifdef OLD_ENVIRON + if (my_state_is_will(TELOPT_OLD_ENVIRON)) + send_wont(TELOPT_OLD_ENVIRON, 1); /* turn off the old */ + goto env_common; + case TELOPT_OLD_ENVIRON: /* Old environment variable option */ + if (my_state_is_will(TELOPT_NEW_ENVIRON)) + break; /* Don't enable if new one is in use! */ + env_common: + telopt_environ = option; +#endif + new_state_ok = 1; + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + if (autologin) + new_state_ok = 1; + break; +#endif + + case TELOPT_XDISPLOC: /* X Display location */ + if (env_getvalue((unsigned char *)"DISPLAY")) + new_state_ok = 1; + break; + + case TELOPT_LINEMODE: +#ifdef KLUDGELINEMODE + kludgelinemode = 0; + send_do(TELOPT_SGA, 1); +#endif + set_my_want_state_will(TELOPT_LINEMODE); + send_will(option, 0); + set_my_state_will(TELOPT_LINEMODE); + slc_init(); + return; + + case TELOPT_ECHO: /* We're never going to echo... */ + default: + break; + } + + if (new_state_ok) { + set_my_want_state_will(option); + send_will(option, 0); + setconnmode(0); /* Set new tty mode */ + } else { + will_wont_resp[option]++; + send_wont(option, 0); + } + } else { + /* + * Handle options that need more things done after the + * other side has acknowledged the option. + */ + switch (option) { + case TELOPT_LINEMODE: +#ifdef KLUDGELINEMODE + kludgelinemode = 0; + send_do(TELOPT_SGA, 1); +#endif + set_my_state_will(option); + slc_init(); + send_do(TELOPT_SGA, 0); + return; + } + } + } + set_my_state_will(option); +} + + static void +dontoption(option) + int option; +{ + + if (will_wont_resp[option]) { + --will_wont_resp[option]; + if (will_wont_resp[option] && my_state_is_wont(option)) + --will_wont_resp[option]; + } + + if ((will_wont_resp[option] == 0) && my_want_state_is_will(option)) { + switch (option) { + case TELOPT_LINEMODE: + linemode = 0; /* put us back to the default state */ + break; +#ifdef OLD_ENVIRON + case TELOPT_NEW_ENVIRON: + /* + * The new environ option wasn't recognized, try + * the old one. + */ + send_will(TELOPT_OLD_ENVIRON, 1); + telopt_environ = TELOPT_OLD_ENVIRON; + break; +#endif + } + /* we always accept a DONT */ + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + setconnmode(0); /* Set new tty mode */ + } + set_my_state_wont(option); +} + +/* + * Given a buffer returned by tgetent(), this routine will turn + * the pipe seperated list of names in the buffer into an array + * of pointers to null terminated names. We toss out any bad, + * duplicate, or verbose names (names with spaces). + */ + +static char *name_unknown = "UNKNOWN"; +static char *unknown[] = { 0, 0 }; + + char ** +mklist(buf, name) + char *buf, *name; +{ + register int n; + register char c, *cp, **argvp, *cp2, **argv, **avt; + + if (name) { + if ((int)strlen(name) > 40) { + name = 0; + unknown[0] = name_unknown; + } else { + unknown[0] = name; + upcase(name); + } + } else + unknown[0] = name_unknown; + /* + * Count up the number of names. + */ + for (n = 1, cp = buf; *cp && *cp != ':'; cp++) { + if (*cp == '|') + n++; + } + /* + * Allocate an array to put the name pointers into + */ + argv = (char **)malloc((n+3)*sizeof(char *)); + if (argv == 0) + return(unknown); + + /* + * Fill up the array of pointers to names. + */ + *argv = 0; + argvp = argv+1; + n = 0; + for (cp = cp2 = buf; (c = *cp); cp++) { + if (c == '|' || c == ':') { + *cp++ = '\0'; + /* + * Skip entries that have spaces or are over 40 + * characters long. If this is our environment + * name, then put it up front. Otherwise, as + * long as this is not a duplicate name (case + * insensitive) add it to the list. + */ + if (n || (cp - cp2 > 41)) + ; + else if (name && (strncasecmp(name, cp2, cp-cp2) == 0)) + *argv = cp2; + else if (is_unique(cp2, argv+1, argvp)) + *argvp++ = cp2; + if (c == ':') + break; + /* + * Skip multiple delimiters. Reset cp2 to + * the beginning of the next name. Reset n, + * the flag for names with spaces. + */ + while ((c = *cp) == '|') + cp++; + cp2 = cp; + n = 0; + } + /* + * Skip entries with spaces or non-ascii values. + * Convert lower case letters to upper case. + */ + if ((c == ' ') || !isascii(c)) + n = 1; + else if (islower(c)) + *cp = toupper(c); + } + + /* + * Check for an old V6 2 character name. If the second + * name points to the beginning of the buffer, and is + * only 2 characters long, move it to the end of the array. + */ + if ((argv[1] == buf) && (strlen(argv[1]) == 2)) { + --argvp; + for (avt = &argv[1]; avt < argvp; avt++) + *avt = *(avt+1); + *argvp++ = buf; + } + + /* + * Duplicate last name, for TTYPE option, and null + * terminate the array. If we didn't find a match on + * our terminal name, put that name at the beginning. + */ + cp = *(argvp-1); + *argvp++ = cp; + *argvp = 0; + + if (*argv == 0) { + if (name) + *argv = name; + else { + --argvp; + for (avt = argv; avt < argvp; avt++) + *avt = *(avt+1); + } + } + if (*argv) + return(argv); + else + return(unknown); +} + + int +is_unique(name, as, ae) + register char *name, **as, **ae; +{ + register char **ap; + register int n; + + n = strlen(name) + 1; + for (ap = as; ap < ae; ap++) + if (strncasecmp(*ap, name, n) == 0) + return(0); + return (1); +} + +#ifdef TERMCAP +char termbuf[1024]; + + /*ARGSUSED*/ + int +setupterm(tname, fd, errp) + char *tname; + int fd, *errp; +{ + if (tgetent(termbuf, tname) == 1) { + termbuf[1023] = '\0'; + if (errp) + *errp = 1; + return(0); + } + if (errp) + *errp = 0; + return(-1); +} +#else +#define termbuf ttytype +extern char ttytype[]; +#endif + +int resettermname = 1; + + char * +gettermname() +{ + char *tname; + static char **tnamep = 0; + static char **next; + int err; + + if (resettermname) { + resettermname = 0; + if (tnamep && tnamep != unknown) + free(tnamep); + if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) && + (setupterm(tname, 1, &err) == 0)) { + tnamep = mklist(termbuf, tname); + } else { + if (tname && ((int)strlen(tname) <= 40)) { + unknown[0] = tname; + upcase(tname); + } else + unknown[0] = name_unknown; + tnamep = unknown; + } + next = tnamep; + } + if (*next == 0) + next = tnamep; + return(*next++); +} +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + * + * Currently we recognize: + * + * Terminal type, send request. + * Terminal speed (send request). + * Local flow control (is request). + * Linemode + */ + + static void +suboption() +{ + unsigned char subchar; + + printsub('<', subbuffer, SB_LEN()+2); + switch (subchar = SB_GET()) { + case TELOPT_TTYPE: + if (my_want_state_is_wont(TELOPT_TTYPE)) + return; + if (SB_EOF() || SB_GET() != TELQUAL_SEND) { + return; + } else { + char *name; + unsigned char temp[50]; + int len; + +#if defined(TN3270) + if (tn3270_ttype()) { + return; + } +#endif /* defined(TN3270) */ + name = gettermname(); + len = strlen(name) + 4 + 2; + if (len < NETROOM()) { + sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE, + TELQUAL_IS, name, IAC, SE); + ring_supply_data(&netoring, temp, len); + printsub('>', &temp[2], len-2); + } else { + ExitString("No room in buffer for terminal type.\n", 1); + /*NOTREACHED*/ + } + } + break; + case TELOPT_TSPEED: + if (my_want_state_is_wont(TELOPT_TSPEED)) + return; + if (SB_EOF()) + return; + if (SB_GET() == TELQUAL_SEND) { + long ospeed, ispeed; + unsigned char temp[50]; + int len; + + TerminalSpeeds(&ispeed, &ospeed); + + sprintf((char *)temp, "%c%c%c%c%d,%d%c%c", IAC, SB, TELOPT_TSPEED, + TELQUAL_IS, ospeed, ispeed, IAC, SE); + len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ + + if (len < NETROOM()) { + ring_supply_data(&netoring, temp, len); + printsub('>', temp+2, len - 2); + } +/*@*/ else printf("lm_will: not enough room in buffer\n"); + } + break; + case TELOPT_LFLOW: + if (my_want_state_is_wont(TELOPT_LFLOW)) + return; + if (SB_EOF()) + return; + switch(SB_GET()) { + case LFLOW_RESTART_ANY: + restartany = 1; + break; + case LFLOW_RESTART_XON: + restartany = 0; + break; + case LFLOW_ON: + localflow = 1; + break; + case LFLOW_OFF: + localflow = 0; + break; + default: + return; + } + setcommandmode(); + setconnmode(0); + break; + + case TELOPT_LINEMODE: + if (my_want_state_is_wont(TELOPT_LINEMODE)) + return; + if (SB_EOF()) + return; + switch (SB_GET()) { + case WILL: + lm_will(subpointer, SB_LEN()); + break; + case WONT: + lm_wont(subpointer, SB_LEN()); + break; + case DO: + lm_do(subpointer, SB_LEN()); + break; + case DONT: + lm_dont(subpointer, SB_LEN()); + break; + case LM_SLC: + slc(subpointer, SB_LEN()); + break; + case LM_MODE: + lm_mode(subpointer, SB_LEN(), 0); + break; + default: + break; + } + break; + +#ifdef OLD_ENVIRON + case TELOPT_OLD_ENVIRON: +#endif + case TELOPT_NEW_ENVIRON: + if (SB_EOF()) + return; + switch(SB_PEEK()) { + case TELQUAL_IS: + case TELQUAL_INFO: + if (my_want_state_is_dont(subchar)) + return; + break; + case TELQUAL_SEND: + if (my_want_state_is_wont(subchar)) { + return; + } + break; + default: + return; + } + env_opt(subpointer, SB_LEN()); + break; + + case TELOPT_XDISPLOC: + if (my_want_state_is_wont(TELOPT_XDISPLOC)) + return; + if (SB_EOF()) + return; + if (SB_GET() == TELQUAL_SEND) { + unsigned char temp[50], *dp; + int len; + + if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) { + /* + * Something happened, we no longer have a DISPLAY + * variable. So, turn off the option. + */ + send_wont(TELOPT_XDISPLOC, 1); + break; + } + sprintf((char *)temp, "%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC, + TELQUAL_IS, dp, IAC, SE); + len = strlen((char *)temp+4) + 4; /* temp[3] is 0 ... */ + + if (len < NETROOM()) { + ring_supply_data(&netoring, temp, len); + printsub('>', temp+2, len - 2); + } +/*@*/ else printf("lm_will: not enough room in buffer\n"); + } + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: { + if (!autologin) + break; + if (SB_EOF()) + return; + switch(SB_GET()) { + case TELQUAL_IS: + if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) + return; + auth_is(subpointer, SB_LEN()); + break; + case TELQUAL_SEND: + if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) + return; + auth_send(subpointer, SB_LEN()); + break; + case TELQUAL_REPLY: + if (my_want_state_is_wont(TELOPT_AUTHENTICATION)) + return; + auth_reply(subpointer, SB_LEN()); + break; + case TELQUAL_NAME: + if (my_want_state_is_dont(TELOPT_AUTHENTICATION)) + return; + auth_name(subpointer, SB_LEN()); + break; + } + } + break; +#endif +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + if (SB_EOF()) + return; + switch(SB_GET()) { + case ENCRYPT_START: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_start(subpointer, SB_LEN()); + break; + case ENCRYPT_END: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_end(); + break; + case ENCRYPT_SUPPORT: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_support(subpointer, SB_LEN()); + break; + case ENCRYPT_REQSTART: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_request_start(subpointer, SB_LEN()); + break; + case ENCRYPT_REQEND: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + /* + * We can always send an REQEND so that we cannot + * get stuck encrypting. We should only get this + * if we have been able to get in the correct mode + * anyhow. + */ + encrypt_request_end(); + break; + case ENCRYPT_IS: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_is(subpointer, SB_LEN()); + break; + case ENCRYPT_REPLY: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_reply(subpointer, SB_LEN()); + break; + case ENCRYPT_ENC_KEYID: + if (my_want_state_is_dont(TELOPT_ENCRYPT)) + return; + encrypt_enc_keyid(subpointer, SB_LEN()); + break; + case ENCRYPT_DEC_KEYID: + if (my_want_state_is_wont(TELOPT_ENCRYPT)) + return; + encrypt_dec_keyid(subpointer, SB_LEN()); + break; + default: + break; + } + break; +#endif /* ENCRYPTION */ + default: + break; + } +} + +static unsigned char str_lm[] = { IAC, SB, TELOPT_LINEMODE, 0, 0, IAC, SE }; + + void +lm_will(cmd, len) + unsigned char *cmd; + int len; +{ + if (len < 1) { +/*@*/ printf("lm_will: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: /* We shouldn't ever get this... */ + default: + str_lm[3] = DONT; + str_lm[4] = cmd[0]; + if (NETROOM() > sizeof(str_lm)) { + ring_supply_data(&netoring, str_lm, sizeof(str_lm)); + printsub('>', &str_lm[2], sizeof(str_lm)-2); + } +/*@*/ else printf("lm_will: not enough room in buffer\n"); + break; + } +} + + void +lm_wont(cmd, len) + unsigned char *cmd; + int len; +{ + if (len < 1) { +/*@*/ printf("lm_wont: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: /* We shouldn't ever get this... */ + default: + /* We are always DONT, so don't respond */ + return; + } +} + + void +lm_do(cmd, len) + unsigned char *cmd; + int len; +{ + if (len < 1) { +/*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: + default: + str_lm[3] = WONT; + str_lm[4] = cmd[0]; + if (NETROOM() > sizeof(str_lm)) { + ring_supply_data(&netoring, str_lm, sizeof(str_lm)); + printsub('>', &str_lm[2], sizeof(str_lm)-2); + } +/*@*/ else printf("lm_do: not enough room in buffer\n"); + break; + } +} + + void +lm_dont(cmd, len) + unsigned char *cmd; + int len; +{ + if (len < 1) { +/*@*/ printf("lm_dont: no command!!!\n"); /* Should not happen... */ + return; + } + switch(cmd[0]) { + case LM_FORWARDMASK: + default: + /* we are always WONT, so don't respond */ + break; + } +} + +static unsigned char str_lm_mode[] = { + IAC, SB, TELOPT_LINEMODE, LM_MODE, 0, IAC, SE +}; + + void +lm_mode(cmd, len, init) + unsigned char *cmd; + int len, init; +{ + if (len != 1) + return; + if ((linemode&MODE_MASK&~MODE_ACK) == *cmd) + return; + if (*cmd&MODE_ACK) + return; + linemode = *cmd&(MODE_MASK&~MODE_ACK); + str_lm_mode[4] = linemode; + if (!init) + str_lm_mode[4] |= MODE_ACK; + if (NETROOM() > sizeof(str_lm_mode)) { + ring_supply_data(&netoring, str_lm_mode, sizeof(str_lm_mode)); + printsub('>', &str_lm_mode[2], sizeof(str_lm_mode)-2); + } +/*@*/ else printf("lm_mode: not enough room in buffer\n"); + setconnmode(0); /* set changed mode */ +} + + + +/* + * slc() + * Handle special character suboption of LINEMODE. + */ + +struct spc { + cc_t val; + cc_t *valp; + char flags; /* Current flags & level */ + char mylevel; /* Maximum level & flags */ +} spc_data[NSLC+1]; + +#define SLC_IMPORT 0 +#define SLC_EXPORT 1 +#define SLC_RVALUE 2 +static int slc_mode = SLC_EXPORT; + + void +slc_init() +{ + register struct spc *spcp; + + localchars = 1; + for (spcp = spc_data; spcp < &spc_data[NSLC+1]; spcp++) { + spcp->val = 0; + spcp->valp = 0; + spcp->flags = spcp->mylevel = SLC_NOSUPPORT; + } + +#define initfunc(func, flags) { \ + spcp = &spc_data[func]; \ + if (spcp->valp = tcval(func)) { \ + spcp->val = *spcp->valp; \ + spcp->mylevel = SLC_VARIABLE|flags; \ + } else { \ + spcp->val = 0; \ + spcp->mylevel = SLC_DEFAULT; \ + } \ + } + + initfunc(SLC_SYNCH, 0); + /* No BRK */ + initfunc(SLC_AO, 0); + initfunc(SLC_AYT, 0); + /* No EOR */ + initfunc(SLC_ABORT, SLC_FLUSHIN|SLC_FLUSHOUT); + initfunc(SLC_EOF, 0); +#ifndef SYSV_TERMIO + initfunc(SLC_SUSP, SLC_FLUSHIN); +#endif + initfunc(SLC_EC, 0); + initfunc(SLC_EL, 0); +#ifndef SYSV_TERMIO + initfunc(SLC_EW, 0); + initfunc(SLC_RP, 0); + initfunc(SLC_LNEXT, 0); +#endif + initfunc(SLC_XON, 0); + initfunc(SLC_XOFF, 0); +#ifdef SYSV_TERMIO + spc_data[SLC_XON].mylevel = SLC_CANTCHANGE; + spc_data[SLC_XOFF].mylevel = SLC_CANTCHANGE; +#endif + initfunc(SLC_FORW1, 0); +#ifdef USE_TERMIO + initfunc(SLC_FORW2, 0); + /* No FORW2 */ +#endif + + initfunc(SLC_IP, SLC_FLUSHIN|SLC_FLUSHOUT); +#undef initfunc + + if (slc_mode == SLC_EXPORT) + slc_export(); + else + slc_import(1); + +} + + void +slcstate() +{ + printf("Special characters are %s values\n", + slc_mode == SLC_IMPORT ? "remote default" : + slc_mode == SLC_EXPORT ? "local" : + "remote"); +} + + void +slc_mode_export() +{ + slc_mode = SLC_EXPORT; + if (my_state_is_will(TELOPT_LINEMODE)) + slc_export(); +} + + void +slc_mode_import(def) + int def; +{ + slc_mode = def ? SLC_IMPORT : SLC_RVALUE; + if (my_state_is_will(TELOPT_LINEMODE)) + slc_import(def); +} + +unsigned char slc_import_val[] = { + IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE +}; +unsigned char slc_import_def[] = { + IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE +}; + + void +slc_import(def) + int def; +{ + if (NETROOM() > sizeof(slc_import_val)) { + if (def) { + ring_supply_data(&netoring, slc_import_def, sizeof(slc_import_def)); + printsub('>', &slc_import_def[2], sizeof(slc_import_def)-2); + } else { + ring_supply_data(&netoring, slc_import_val, sizeof(slc_import_val)); + printsub('>', &slc_import_val[2], sizeof(slc_import_val)-2); + } + } +/*@*/ else printf("slc_import: not enough room\n"); +} + + void +slc_export() +{ + register struct spc *spcp; + + TerminalDefaultChars(); + + slc_start_reply(); + for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { + if (spcp->mylevel != SLC_NOSUPPORT) { + if (spcp->val == (cc_t)(_POSIX_VDISABLE)) + spcp->flags = SLC_NOSUPPORT; + else + spcp->flags = spcp->mylevel; + if (spcp->valp) + spcp->val = *spcp->valp; + slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); + } + } + slc_end_reply(); + (void)slc_update(); + setconnmode(1); /* Make sure the character values are set */ +} + + void +slc(cp, len) + register unsigned char *cp; + int len; +{ + register struct spc *spcp; + register int func,level; + + slc_start_reply(); + + for (; len >= 3; len -=3, cp +=3) { + + func = cp[SLC_FUNC]; + + if (func == 0) { + /* + * Client side: always ignore 0 function. + */ + continue; + } + if (func > NSLC) { + if ((cp[SLC_FLAGS] & SLC_LEVELBITS) != SLC_NOSUPPORT) + slc_add_reply(func, SLC_NOSUPPORT, 0); + continue; + } + + spcp = &spc_data[func]; + + level = cp[SLC_FLAGS]&(SLC_LEVELBITS|SLC_ACK); + + if ((cp[SLC_VALUE] == (unsigned char)spcp->val) && + ((level&SLC_LEVELBITS) == (spcp->flags&SLC_LEVELBITS))) { + continue; + } + + if (level == (SLC_DEFAULT|SLC_ACK)) { + /* + * This is an error condition, the SLC_ACK + * bit should never be set for the SLC_DEFAULT + * level. Our best guess to recover is to + * ignore the SLC_ACK bit. + */ + cp[SLC_FLAGS] &= ~SLC_ACK; + } + + if (level == ((spcp->flags&SLC_LEVELBITS)|SLC_ACK)) { + spcp->val = (cc_t)cp[SLC_VALUE]; + spcp->flags = cp[SLC_FLAGS]; /* include SLC_ACK */ + continue; + } + + level &= ~SLC_ACK; + + if (level <= (spcp->mylevel&SLC_LEVELBITS)) { + spcp->flags = cp[SLC_FLAGS]|SLC_ACK; + spcp->val = (cc_t)cp[SLC_VALUE]; + } + if (level == SLC_DEFAULT) { + if ((spcp->mylevel&SLC_LEVELBITS) != SLC_DEFAULT) + spcp->flags = spcp->mylevel; + else + spcp->flags = SLC_NOSUPPORT; + } + slc_add_reply(func, spcp->flags, spcp->val); + } + slc_end_reply(); + if (slc_update()) + setconnmode(1); /* set the new character values */ +} + + void +slc_check() +{ + register struct spc *spcp; + + slc_start_reply(); + for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { + if (spcp->valp && spcp->val != *spcp->valp) { + spcp->val = *spcp->valp; + if (spcp->val == (cc_t)(_POSIX_VDISABLE)) + spcp->flags = SLC_NOSUPPORT; + else + spcp->flags = spcp->mylevel; + slc_add_reply(spcp - spc_data, spcp->flags, spcp->val); + } + } + slc_end_reply(); + setconnmode(1); +} + + +unsigned char slc_reply[128]; +unsigned char *slc_replyp; + + void +slc_start_reply() +{ + slc_replyp = slc_reply; + *slc_replyp++ = IAC; + *slc_replyp++ = SB; + *slc_replyp++ = TELOPT_LINEMODE; + *slc_replyp++ = LM_SLC; +} + + void +slc_add_reply(func, flags, value) + unsigned char func; + unsigned char flags; + cc_t value; +{ + if ((*slc_replyp++ = func) == IAC) + *slc_replyp++ = IAC; + if ((*slc_replyp++ = flags) == IAC) + *slc_replyp++ = IAC; + if ((*slc_replyp++ = (unsigned char)value) == IAC) + *slc_replyp++ = IAC; +} + + void +slc_end_reply() +{ + register int len; + + *slc_replyp++ = IAC; + *slc_replyp++ = SE; + len = slc_replyp - slc_reply; + if (len <= 6) + return; + if (NETROOM() > len) { + ring_supply_data(&netoring, slc_reply, slc_replyp - slc_reply); + printsub('>', &slc_reply[2], slc_replyp - slc_reply - 2); + } +/*@*/else printf("slc_end_reply: not enough room\n"); +} + + int +slc_update() +{ + register struct spc *spcp; + int need_update = 0; + + for (spcp = &spc_data[1]; spcp < &spc_data[NSLC+1]; spcp++) { + if (!(spcp->flags&SLC_ACK)) + continue; + spcp->flags &= ~SLC_ACK; + if (spcp->valp && (*spcp->valp != spcp->val)) { + *spcp->valp = spcp->val; + need_update = 1; + } + } + return(need_update); +} + +#ifdef OLD_ENVIRON +# ifdef ENV_HACK +/* + * Earlier version of telnet/telnetd from the BSD code had + * the definitions of VALUE and VAR reversed. To ensure + * maximum interoperability, we assume that the server is + * an older BSD server, until proven otherwise. The newer + * BSD servers should be able to handle either definition, + * so it is better to use the wrong values if we don't + * know what type of server it is. + */ +int env_auto = 1; +int old_env_var = OLD_ENV_VAR; +int old_env_value = OLD_ENV_VALUE; +# else +# define old_env_var OLD_ENV_VAR +# define old_env_value OLD_ENV_VALUE +# endif +#endif + + void +env_opt(buf, len) + register unsigned char *buf; + register int len; +{ + register unsigned char *ep = 0, *epc = 0; + register int i; + + switch(buf[0]&0xff) { + case TELQUAL_SEND: + env_opt_start(); + if (len == 1) { + env_opt_add(NULL); + } else for (i = 1; i < len; i++) { + switch (buf[i]&0xff) { +#ifdef OLD_ENVIRON + case OLD_ENV_VAR: +# ifdef ENV_HACK + if (telopt_environ == TELOPT_OLD_ENVIRON + && env_auto) { + /* Server has the same definitions */ + old_env_var = OLD_ENV_VAR; + old_env_value = OLD_ENV_VALUE; + } + /* FALL THROUGH */ +# endif + case OLD_ENV_VALUE: + /* + * Although OLD_ENV_VALUE is not legal, we will + * still recognize it, just in case it is an + * old server that has VAR & VALUE mixed up... + */ + /* FALL THROUGH */ +#else + case NEW_ENV_VAR: +#endif + case ENV_USERVAR: + if (ep) { + *epc = 0; + env_opt_add(ep); + } + ep = epc = &buf[i+1]; + break; + case ENV_ESC: + i++; + /*FALL THROUGH*/ + default: + if (epc) + *epc++ = buf[i]; + break; + } + } + if (ep) { + *epc = 0; + env_opt_add(ep); + } + env_opt_end(1); + break; + + case TELQUAL_IS: + case TELQUAL_INFO: + /* Ignore for now. We shouldn't get it anyway. */ + break; + + default: + break; + } +} + +#define OPT_REPLY_SIZE 256 +unsigned char *opt_reply; +unsigned char *opt_replyp; +unsigned char *opt_replyend; + + void +env_opt_start() +{ + if (opt_reply) + opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE); + else + opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE); + if (opt_reply == NULL) { +/*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n"); + opt_reply = opt_replyp = opt_replyend = NULL; + return; + } + opt_replyp = opt_reply; + opt_replyend = opt_reply + OPT_REPLY_SIZE; + *opt_replyp++ = IAC; + *opt_replyp++ = SB; + *opt_replyp++ = telopt_environ; + *opt_replyp++ = TELQUAL_IS; +} + + void +env_opt_start_info() +{ + env_opt_start(); + if (opt_replyp) + opt_replyp[-1] = TELQUAL_INFO; +} + + void +env_opt_add(ep) + register unsigned char *ep; +{ + register unsigned char *vp, c; + + if (opt_reply == NULL) /*XXX*/ + return; /*XXX*/ + + if (ep == NULL || *ep == '\0') { + /* Send user defined variables first. */ + env_default(1, 0); + while (ep = env_default(0, 0)) + env_opt_add(ep); + + /* Now add the list of well know variables. */ + env_default(1, 1); + while (ep = env_default(0, 1)) + env_opt_add(ep); + return; + } + vp = env_getvalue(ep); + if (opt_replyp + (vp ? strlen((char *)vp) : 0) + + strlen((char *)ep) + 6 > opt_replyend) + { + register int len; + opt_replyend += OPT_REPLY_SIZE; + len = opt_replyend - opt_reply; + opt_reply = (unsigned char *)realloc(opt_reply, len); + if (opt_reply == NULL) { +/*@*/ printf("env_opt_add: realloc() failed!!!\n"); + opt_reply = opt_replyp = opt_replyend = NULL; + return; + } + opt_replyp = opt_reply + len - (opt_replyend - opt_replyp); + opt_replyend = opt_reply + len; + } + if (opt_welldefined(ep)) +#ifdef OLD_ENVIRON + if (telopt_environ == TELOPT_OLD_ENVIRON) + *opt_replyp++ = old_env_var; + else +#endif + *opt_replyp++ = NEW_ENV_VAR; + else + *opt_replyp++ = ENV_USERVAR; + for (;;) { + while (c = *ep++) { + switch(c&0xff) { + case IAC: + *opt_replyp++ = IAC; + break; + case NEW_ENV_VAR: + case NEW_ENV_VALUE: + case ENV_ESC: + case ENV_USERVAR: + *opt_replyp++ = ENV_ESC; + break; + } + *opt_replyp++ = c; + } + if (ep = vp) { +#ifdef OLD_ENVIRON + if (telopt_environ == TELOPT_OLD_ENVIRON) + *opt_replyp++ = old_env_value; + else +#endif + *opt_replyp++ = NEW_ENV_VALUE; + vp = NULL; + } else + break; + } +} + + int +opt_welldefined(ep) + char *ep; +{ + if ((strcmp(ep, "USER") == 0) || + (strcmp(ep, "DISPLAY") == 0) || + (strcmp(ep, "PRINTER") == 0) || + (strcmp(ep, "SYSTEMTYPE") == 0) || + (strcmp(ep, "JOB") == 0) || + (strcmp(ep, "ACCT") == 0)) + return(1); + return(0); +} + void +env_opt_end(emptyok) + register int emptyok; +{ + register int len; + + len = opt_replyp - opt_reply + 2; + if (emptyok || len > 6) { + *opt_replyp++ = IAC; + *opt_replyp++ = SE; + if (NETROOM() > len) { + ring_supply_data(&netoring, opt_reply, len); + printsub('>', &opt_reply[2], len - 2); + } +/*@*/ else printf("slc_end_reply: not enough room\n"); + } + if (opt_reply) { + free(opt_reply); + opt_reply = opt_replyp = opt_replyend = NULL; + } +} + + + + int +telrcv() +{ + register int c; + register int scc; + register unsigned char *sbp; + int count; + int returnValue = 0; + + scc = 0; + count = 0; + while (TTYROOM() > 2) { + if (scc == 0) { + if (count) { + ring_consumed(&netiring, count); + returnValue = 1; + count = 0; + } + sbp = netiring.consume; + scc = ring_full_consecutive(&netiring); + if (scc == 0) { + /* No more data coming in */ + break; + } + } + + c = *sbp++ & 0xff, scc--; count++; +#ifdef ENCRYPTION + if (decrypt_input) + c = (*decrypt_input)(c); +#endif /* ENCRYPTION */ + + switch (telrcv_state) { + + case TS_CR: + telrcv_state = TS_DATA; + if (c == '\0') { + break; /* Ignore \0 after CR */ + } + else if ((c == '\n') && my_want_state_is_dont(TELOPT_ECHO) && !crmod) { + TTYADD(c); + break; + } + /* Else, fall through */ + + case TS_DATA: + if (c == IAC) { + telrcv_state = TS_IAC; + break; + } +# if defined(TN3270) + if (In3270) { + *Ifrontp++ = c; + while (scc > 0) { + c = *sbp++ & 0377, scc--; count++; +#ifdef ENCRYPTION + if (decrypt_input) + c = (*decrypt_input)(c); +#endif /* ENCRYPTION */ + if (c == IAC) { + telrcv_state = TS_IAC; + break; + } + *Ifrontp++ = c; + } + } else +# endif /* defined(TN3270) */ + /* + * The 'crmod' hack (see following) is needed + * since we can't * set CRMOD on output only. + * Machines like MULTICS like to send \r without + * \n; since we must turn off CRMOD to get proper + * input, the mapping is done here (sigh). + */ + if ((c == '\r') && my_want_state_is_dont(TELOPT_BINARY)) { + if (scc > 0) { + c = *sbp&0xff; +#ifdef ENCRYPTION + if (decrypt_input) + c = (*decrypt_input)(c); +#endif /* ENCRYPTION */ + if (c == 0) { + sbp++, scc--; count++; + /* a "true" CR */ + TTYADD('\r'); + } else if (my_want_state_is_dont(TELOPT_ECHO) && + (c == '\n')) { + sbp++, scc--; count++; + TTYADD('\n'); + } else { +#ifdef ENCRYPTION + if (decrypt_input) + (*decrypt_input)(-1); +#endif /* ENCRYPTION */ + + TTYADD('\r'); + if (crmod) { + TTYADD('\n'); + } + } + } else { + telrcv_state = TS_CR; + TTYADD('\r'); + if (crmod) { + TTYADD('\n'); + } + } + } else { + TTYADD(c); + } + continue; + + case TS_IAC: +process_iac: + switch (c) { + + case WILL: + telrcv_state = TS_WILL; + continue; + + case WONT: + telrcv_state = TS_WONT; + continue; + + case DO: + telrcv_state = TS_DO; + continue; + + case DONT: + telrcv_state = TS_DONT; + continue; + + case DM: + /* + * We may have missed an urgent notification, + * so make sure we flush whatever is in the + * buffer currently. + */ + printoption("RCVD", IAC, DM); + SYNCHing = 1; + (void) ttyflush(1); + SYNCHing = stilloob(); + settimer(gotDM); + break; + + case SB: + SB_CLEAR(); + telrcv_state = TS_SB; + continue; + +# if defined(TN3270) + case EOR: + if (In3270) { + if (Ibackp == Ifrontp) { + Ibackp = Ifrontp = Ibuf; + ISend = 0; /* should have been! */ + } else { + Ibackp += DataFromNetwork(Ibackp, Ifrontp-Ibackp, 1); + ISend = 1; + } + } + printoption("RCVD", IAC, EOR); + break; +# endif /* defined(TN3270) */ + + case IAC: +# if !defined(TN3270) + TTYADD(IAC); +# else /* !defined(TN3270) */ + if (In3270) { + *Ifrontp++ = IAC; + } else { + TTYADD(IAC); + } +# endif /* !defined(TN3270) */ + break; + + case NOP: + case GA: + default: + printoption("RCVD", IAC, c); + break; + } + telrcv_state = TS_DATA; + continue; + + case TS_WILL: + printoption("RCVD", WILL, c); + willoption(c); + SetIn3270(); + telrcv_state = TS_DATA; + continue; + + case TS_WONT: + printoption("RCVD", WONT, c); + wontoption(c); + SetIn3270(); + telrcv_state = TS_DATA; + continue; + + case TS_DO: + printoption("RCVD", DO, c); + dooption(c); + SetIn3270(); + if (c == TELOPT_NAWS) { + sendnaws(); + } else if (c == TELOPT_LFLOW) { + localflow = 1; + setcommandmode(); + setconnmode(0); + } + telrcv_state = TS_DATA; + continue; + + case TS_DONT: + printoption("RCVD", DONT, c); + dontoption(c); + flushline = 1; + setconnmode(0); /* set new tty mode (maybe) */ + SetIn3270(); + telrcv_state = TS_DATA; + continue; + + case TS_SB: + if (c == IAC) { + telrcv_state = TS_SE; + } else { + SB_ACCUM(c); + } + continue; + + case TS_SE: + if (c != SE) { + if (c != IAC) { + /* + * This is an error. We only expect to get + * "IAC IAC" or "IAC SE". Several things may + * have happend. An IAC was not doubled, the + * IAC SE was left off, or another option got + * inserted into the suboption are all possibilities. + * If we assume that the IAC was not doubled, + * and really the IAC SE was left off, we could + * get into an infinate loop here. So, instead, + * we terminate the suboption, and process the + * partial suboption if we can. + */ + SB_ACCUM(IAC); + SB_ACCUM(c); + subpointer -= 2; + SB_TERM(); + + printoption("In SUBOPTION processing, RCVD", IAC, c); + suboption(); /* handle sub-option */ + SetIn3270(); + telrcv_state = TS_IAC; + goto process_iac; + } + SB_ACCUM(c); + telrcv_state = TS_SB; + } else { + SB_ACCUM(IAC); + SB_ACCUM(SE); + subpointer -= 2; + SB_TERM(); + suboption(); /* handle sub-option */ + SetIn3270(); + telrcv_state = TS_DATA; + } + } + } + if (count) + ring_consumed(&netiring, count); + return returnValue||count; +} + +static int bol = 1, local = 0; + + int +rlogin_susp() +{ + if (local) { + local = 0; + bol = 1; + command(0, "z\n", 2); + return(1); + } + return(0); +} + + static int +telsnd() +{ + int tcc; + int count; + int returnValue = 0; + unsigned char *tbp; + + tcc = 0; + count = 0; + while (NETROOM() > 2) { + register int sc; + register int c; + + if (tcc == 0) { + if (count) { + ring_consumed(&ttyiring, count); + returnValue = 1; + count = 0; + } + tbp = ttyiring.consume; + tcc = ring_full_consecutive(&ttyiring); + if (tcc == 0) { + break; + } + } + c = *tbp++ & 0xff, sc = strip(c), tcc--; count++; + if (rlogin != _POSIX_VDISABLE) { + if (bol) { + bol = 0; + if (sc == rlogin) { + local = 1; + continue; + } + } else if (local) { + local = 0; + if (sc == '.' || c == termEofChar) { + bol = 1; + command(0, "close\n", 6); + continue; + } + if (sc == termSuspChar) { + bol = 1; + command(0, "z\n", 2); + continue; + } + if (sc == escape) { + command(0, (char *)tbp, tcc); + bol = 1; + count += tcc; + tcc = 0; + flushline = 1; + break; + } + if (sc != rlogin) { + ++tcc; + --tbp; + --count; + c = sc = rlogin; + } + } + if ((sc == '\n') || (sc == '\r')) + bol = 1; + } else if (sc == escape) { + /* + * Double escape is a pass through of a single escape character. + */ + if (tcc && strip(*tbp) == escape) { + tbp++; + tcc--; + count++; + bol = 0; + } else { + command(0, (char *)tbp, tcc); + bol = 1; + count += tcc; + tcc = 0; + flushline = 1; + break; + } + } else + bol = 0; +#ifdef KLUDGELINEMODE + if (kludgelinemode && (globalmode&MODE_EDIT) && (sc == echoc)) { + if (tcc > 0 && strip(*tbp) == echoc) { + tcc--; tbp++; count++; + } else { + dontlecho = !dontlecho; + settimer(echotoggle); + setconnmode(0); + flushline = 1; + break; + } + } +#endif + if (MODE_LOCAL_CHARS(globalmode)) { + if (TerminalSpecialChars(sc) == 0) { + bol = 1; + break; + } + } + if (my_want_state_is_wont(TELOPT_BINARY)) { + switch (c) { + case '\n': + /* + * If we are in CRMOD mode (\r ==> \n) + * on our local machine, then probably + * a newline (unix) is CRLF (TELNET). + */ + if (MODE_LOCAL_CHARS(globalmode)) { + NETADD('\r'); + } + NETADD('\n'); + bol = flushline = 1; + break; + case '\r': + if (!crlf) { + NET2ADD('\r', '\0'); + } else { + NET2ADD('\r', '\n'); + } + bol = flushline = 1; + break; + case IAC: + NET2ADD(IAC, IAC); + break; + default: + NETADD(c); + break; + } + } else if (c == IAC) { + NET2ADD(IAC, IAC); + } else { + NETADD(c); + } + } + if (count) + ring_consumed(&ttyiring, count); + return returnValue||count; /* Non-zero if we did anything */ +} + +/* + * Scheduler() + * + * Try to do something. + * + * If we do something useful, return 1; else return 0. + * + */ + + + int +Scheduler(block) + int block; /* should we block in the select ? */ +{ + /* One wants to be a bit careful about setting returnValue + * to one, since a one implies we did some useful work, + * and therefore probably won't be called to block next + * time (TN3270 mode only). + */ + int returnValue; + int netin, netout, netex, ttyin, ttyout; + + /* Decide which rings should be processed */ + + netout = ring_full_count(&netoring) && + (flushline || + (my_want_state_is_wont(TELOPT_LINEMODE) +#ifdef KLUDGELINEMODE + && (!kludgelinemode || my_want_state_is_do(TELOPT_SGA)) +#endif + ) || + my_want_state_is_will(TELOPT_BINARY)); + ttyout = ring_full_count(&ttyoring); + +#if defined(TN3270) + ttyin = ring_empty_count(&ttyiring) && (shell_active == 0); +#else /* defined(TN3270) */ + ttyin = ring_empty_count(&ttyiring); +#endif /* defined(TN3270) */ + +#if defined(TN3270) + netin = ring_empty_count(&netiring); +# else /* !defined(TN3270) */ + netin = !ISend && ring_empty_count(&netiring); +# endif /* !defined(TN3270) */ + + netex = !SYNCHing; + + /* If we have seen a signal recently, reset things */ +# if defined(TN3270) && (defined(unix) || defined(__APPLE__)) + if (HaveInput) { + HaveInput = 0; + (void) signal(SIGIO, inputAvailable); + } +#endif /* defined(TN3270) && (defined(unix) || defined(__APPLE__)) */ + + /* Call to system code to process rings */ + + returnValue = process_rings(netin, netout, netex, ttyin, ttyout, !block); + + /* Now, look at the input rings, looking for work to do. */ + + if (ring_full_count(&ttyiring)) { +# if defined(TN3270) + if (In3270) { + int c; + + c = DataFromTerminal(ttyiring.consume, + ring_full_consecutive(&ttyiring)); + if (c) { + returnValue = 1; + ring_consumed(&ttyiring, c); + } + } else { +# endif /* defined(TN3270) */ + returnValue |= telsnd(); +# if defined(TN3270) + } +# endif /* defined(TN3270) */ + } + + if (ring_full_count(&netiring)) { +# if !defined(TN3270) + returnValue |= telrcv(); +# else /* !defined(TN3270) */ + returnValue = Push3270(); +# endif /* !defined(TN3270) */ + } + return returnValue; +} + +/* + * Select from tty and network... + */ + void +telnet(user) + char *user; +{ + sys_telnet_init(); + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + { + static char local_host[256] = { 0 }; + + if (!local_host[0]) { + gethostname(local_host, sizeof(local_host)); + local_host[sizeof(local_host)-1] = 0; + } + auth_encrypt_init(local_host, hostname, "TELNET", 0); + auth_encrypt_user(user); + } +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ +# if !defined(TN3270) + if (telnetport) { +#if defined(AUTHENTICATION) + if (autologin) + send_will(TELOPT_AUTHENTICATION, 1); +#endif +#ifdef ENCRYPTION + send_do(TELOPT_ENCRYPT, 1); + send_will(TELOPT_ENCRYPT, 1); +#endif /* ENCRYPTION */ + send_do(TELOPT_SGA, 1); + send_will(TELOPT_TTYPE, 1); + send_will(TELOPT_NAWS, 1); + send_will(TELOPT_TSPEED, 1); + send_will(TELOPT_LFLOW, 1); + send_will(TELOPT_LINEMODE, 1); + send_will(TELOPT_NEW_ENVIRON, 1); + send_do(TELOPT_STATUS, 1); + if (env_getvalue((unsigned char *)"DISPLAY")) + send_will(TELOPT_XDISPLOC, 1); + if (eight) + tel_enter_binary(eight); + } +# endif /* !defined(TN3270) */ + +# if !defined(TN3270) + for (;;) { + int schedValue; + + while ((schedValue = Scheduler(0)) != 0) { + if (schedValue == -1) { + setcommandmode(); + return; + } + } + + if (Scheduler(1) == -1) { + setcommandmode(); + return; + } + } +# else /* !defined(TN3270) */ + for (;;) { + int schedValue; + + while (!In3270 && !shell_active) { + if (Scheduler(1) == -1) { + setcommandmode(); + return; + } + } + + while ((schedValue = Scheduler(0)) != 0) { + if (schedValue == -1) { + setcommandmode(); + return; + } + } + /* If there is data waiting to go out to terminal, don't + * schedule any more data for the terminal. + */ + if (ring_full_count(&ttyoring)) { + schedValue = 1; + } else { + if (shell_active) { + if (shell_continue() == 0) { + ConnectScreen(); + } + } else if (In3270) { + schedValue = DoTerminalOutput(); + } + } + if (schedValue && (shell_active == 0)) { + if (Scheduler(1) == -1) { + setcommandmode(); + return; + } + } + } +# endif /* !defined(TN3270) */ +} + +#if 0 /* XXX - this not being in is a bug */ +/* + * nextitem() + * + * Return the address of the next "item" in the TELNET data + * stream. This will be the address of the next character if + * the current address is a user data character, or it will + * be the address of the character following the TELNET command + * if the current address is a TELNET IAC ("I Am a Command") + * character. + */ + + static char * +nextitem(current) + char *current; +{ + if ((*current&0xff) != IAC) { + return current+1; + } + switch (*(current+1)&0xff) { + case DO: + case DONT: + case WILL: + case WONT: + return current+3; + case SB: /* loop forever looking for the SE */ + { + register char *look = current+2; + + for (;;) { + if ((*look++&0xff) == IAC) { + if ((*look++&0xff) == SE) { + return look; + } + } + } + } + default: + return current+2; + } +} +#endif /* 0 */ + +/* + * netclear() + * + * We are about to do a TELNET SYNCH operation. Clear + * the path to the network. + * + * Things are a bit tricky since we may have sent the first + * byte or so of a previous TELNET command into the network. + * So, we have to scan the network buffer from the beginning + * until we are up to where we want to be. + * + * A side effect of what we do, just to keep things + * simple, is to clear the urgent data pointer. The principal + * caller should be setting the urgent data pointer AFTER calling + * us in any case. + */ + + static void +netclear() +{ +#if 0 /* XXX */ + register char *thisitem, *next; + char *good; +#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ + ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) + + thisitem = netobuf; + + while ((next = nextitem(thisitem)) <= netobuf.send) { + thisitem = next; + } + + /* Now, thisitem is first before/at boundary. */ + + good = netobuf; /* where the good bytes go */ + + while (netoring.add > thisitem) { + if (wewant(thisitem)) { + int length; + + next = thisitem; + do { + next = nextitem(next); + } while (wewant(next) && (nfrontp > next)); + length = next-thisitem; + memmove(good, thisitem, length); + good += length; + thisitem = next; + } else { + thisitem = nextitem(thisitem); + } + } + +#endif /* 0 */ +} + +/* + * These routines add various telnet commands to the data stream. + */ + + static void +doflush() +{ + NET2ADD(IAC, DO); + NETADD(TELOPT_TM); + flushline = 1; + flushout = 1; + (void) ttyflush(1); /* Flush/drop output */ + /* do printoption AFTER flush, otherwise the output gets tossed... */ + printoption("SENT", DO, TELOPT_TM); +} + + void +xmitAO() +{ + NET2ADD(IAC, AO); + printoption("SENT", IAC, AO); + if (autoflush) { + doflush(); + } +} + + + void +xmitEL() +{ + NET2ADD(IAC, EL); + printoption("SENT", IAC, EL); +} + + void +xmitEC() +{ + NET2ADD(IAC, EC); + printoption("SENT", IAC, EC); +} + + + int +dosynch() +{ + netclear(); /* clear the path to the network */ + NETADD(IAC); + setneturg(); + NETADD(DM); + printoption("SENT", IAC, DM); + return 1; +} + +int want_status_response = 0; + + int +get_status() +{ + unsigned char tmp[16]; + register unsigned char *cp; + + if (my_want_state_is_dont(TELOPT_STATUS)) { + printf("Remote side does not support STATUS option\n"); + return 0; + } + cp = tmp; + + *cp++ = IAC; + *cp++ = SB; + *cp++ = TELOPT_STATUS; + *cp++ = TELQUAL_SEND; + *cp++ = IAC; + *cp++ = SE; + if (NETROOM() >= cp - tmp) { + ring_supply_data(&netoring, tmp, cp-tmp); + printsub('>', tmp+2, cp - tmp - 2); + } + ++want_status_response; + return 1; +} + + void +intp() +{ + NET2ADD(IAC, IP); + printoption("SENT", IAC, IP); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + + void +sendbrk() +{ + NET2ADD(IAC, BREAK); + printoption("SENT", IAC, BREAK); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + + void +sendabort() +{ + NET2ADD(IAC, ABORT); + printoption("SENT", IAC, ABORT); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + + void +sendsusp() +{ + NET2ADD(IAC, SUSP); + printoption("SENT", IAC, SUSP); + flushline = 1; + if (autoflush) { + doflush(); + } + if (autosynch) { + dosynch(); + } +} + + void +sendeof() +{ + NET2ADD(IAC, xEOF); + printoption("SENT", IAC, xEOF); +} + + void +sendayt() +{ + NET2ADD(IAC, AYT); + printoption("SENT", IAC, AYT); +} + +/* + * Send a window size update to the remote system. + */ + + void +sendnaws() +{ + long rows, cols; + unsigned char tmp[16]; + register unsigned char *cp; + + if (my_state_is_wont(TELOPT_NAWS)) + return; + +#define PUTSHORT(cp, x) { if ((*cp++ = ((x)>>8)&0xff) == IAC) *cp++ = IAC; \ + if ((*cp++ = ((x))&0xff) == IAC) *cp++ = IAC; } + + if (TerminalWindowSize(&rows, &cols) == 0) { /* Failed */ + return; + } + + cp = tmp; + + *cp++ = IAC; + *cp++ = SB; + *cp++ = TELOPT_NAWS; + PUTSHORT(cp, cols); + PUTSHORT(cp, rows); + *cp++ = IAC; + *cp++ = SE; + if (NETROOM() >= cp - tmp) { + ring_supply_data(&netoring, tmp, cp-tmp); + printsub('>', tmp+2, cp - tmp - 2); + } +} + + void +tel_enter_binary(rw) + int rw; +{ + if (rw&1) + send_do(TELOPT_BINARY, 1); + if (rw&2) + send_will(TELOPT_BINARY, 1); +} + + void +tel_leave_binary(rw) + int rw; +{ + if (rw&1) + send_dont(TELOPT_BINARY, 1); + if (rw&2) + send_wont(TELOPT_BINARY, 1); +} diff --git a/telnet.tproj/terminal.c b/telnet.tproj/terminal.c new file mode 100644 index 0000000..de75e4d --- /dev/null +++ b/telnet.tproj/terminal.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)terminal.c 8.2 (Berkeley) 2/16/95"; +#endif /* not lint */ + +#include +#include + +#include "ring.h" + +#include "externs.h" +#include "types.h" + +Ring ttyoring, ttyiring; +unsigned char ttyobuf[2*BUFSIZ], ttyibuf[BUFSIZ]; + +int termdata; /* Debugging flag */ + +#ifdef USE_TERMIO +# ifndef VDISCARD +cc_t termFlushChar; +# endif +# ifndef VLNEXT +cc_t termLiteralNextChar; +# endif +# ifndef VSUSP +cc_t termSuspChar; +# endif +# ifndef VWERASE +cc_t termWerasChar; +# endif +# ifndef VREPRINT +cc_t termRprntChar; +# endif +# ifndef VSTART +cc_t termStartChar; +# endif +# ifndef VSTOP +cc_t termStopChar; +# endif +# ifndef VEOL +cc_t termForw1Char; +# endif +# ifndef VEOL2 +cc_t termForw2Char; +# endif +# ifndef VSTATUS +cc_t termAytChar; +# endif +#else +cc_t termForw2Char; +cc_t termAytChar; +#endif + +/* + * initialize the terminal data structures. + */ + + void +init_terminal() +{ + if (ring_init(&ttyoring, ttyobuf, sizeof ttyobuf) != 1) { + exit(1); + } + if (ring_init(&ttyiring, ttyibuf, sizeof ttyibuf) != 1) { + exit(1); + } + autoflush = TerminalAutoFlush(); +} + + +/* + * Send as much data as possible to the terminal. + * + * Return value: + * -1: No useful work done, data waiting to go out. + * 0: No data was waiting, so nothing was done. + * 1: All waiting data was written out. + * n: All data - n was written out. + */ + + + int +ttyflush(drop) + int drop; +{ + register int n, n0, n1; + + n0 = ring_full_count(&ttyoring); + if ((n1 = n = ring_full_consecutive(&ttyoring)) > 0) { + if (drop) { + TerminalFlushOutput(); + /* we leave 'n' alone! */ + } else { + n = TerminalWrite(ttyoring.consume, n); + } + } + if (n > 0) { + if (termdata && n) { + Dump('>', ttyoring.consume, n); + } + /* + * If we wrote everything, and the full count is + * larger than what we wrote, then write the + * rest of the buffer. + */ + if (n1 == n && n0 > n) { + n1 = n0 - n; + if (!drop) + n1 = TerminalWrite(ttyoring.bottom, n1); + if (n1 > 0) + n += n1; + } + ring_consumed(&ttyoring, n); + } + if (n < 0) + return -1; + if (n == n0) { + if (n0) + return -1; + return 0; + } + return n0 - n + 1; +} + + +/* + * These routines decides on what the mode should be (based on the values + * of various global variables). + */ + + + int +getconnmode() +{ + extern int linemode; + int mode = 0; +#ifdef KLUDGELINEMODE + extern int kludgelinemode; +#endif + + if (In3270) + return(MODE_FLOW); + + if (my_want_state_is_dont(TELOPT_ECHO)) + mode |= MODE_ECHO; + + if (localflow) + mode |= MODE_FLOW; + + if (my_want_state_is_will(TELOPT_BINARY)) + mode |= MODE_INBIN; + + if (his_want_state_is_will(TELOPT_BINARY)) + mode |= MODE_OUTBIN; + +#ifdef KLUDGELINEMODE + if (kludgelinemode) { + if (my_want_state_is_dont(TELOPT_SGA)) { + mode |= (MODE_TRAPSIG|MODE_EDIT); + if (dontlecho && (clocks.echotoggle > clocks.modenegotiated)) { + mode &= ~MODE_ECHO; + } + } + return(mode); + } +#endif + if (my_want_state_is_will(TELOPT_LINEMODE)) + mode |= linemode; + return(mode); +} + + void +setconnmode(force) + int force; +{ +#ifdef ENCRYPTION + static int enc_passwd = 0; +#endif /* ENCRYPTION */ + register int newmode; + + newmode = getconnmode()|(force?MODE_FORCE:0); + + TerminalNewMode(newmode); + +#ifdef ENCRYPTION + if ((newmode & (MODE_ECHO|MODE_EDIT)) == MODE_EDIT) { + if (my_want_state_is_will(TELOPT_ENCRYPT) + && (enc_passwd == 0) && !encrypt_output) { + encrypt_request_start(0, 0); + enc_passwd = 1; + } + } else { + if (enc_passwd) { + encrypt_request_end(); + enc_passwd = 0; + } + } +#endif /* ENCRYPTION */ + +} + + + void +setcommandmode() +{ + TerminalNewMode(-1); +} diff --git a/telnet.tproj/tn3270.c b/telnet.tproj/tn3270.c new file mode 100644 index 0000000..875d386 --- /dev/null +++ b/telnet.tproj/tn3270.c @@ -0,0 +1,434 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)tn3270.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include +#include + +#include "general.h" + +#include "defines.h" +#include "ring.h" +#include "externs.h" +#include "fdset.h" + +#if defined(TN3270) + +#include "../ctlr/screen.h" +#include "../general/globals.h" + +#include "../sys_curses/telextrn.h" +#include "../ctlr/externs.h" + +#if defined(unix) || defined(__APPLE__) +int + HaveInput, /* There is input available to scan */ + cursesdata, /* Do we dump curses data? */ + sigiocount; /* Number of times we got a SIGIO */ + +char tline[200]; +char *transcom = 0; /* transparent mode command (default: none) */ +#endif /* defined(unix) || defined(__APPLE__) */ + +char Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp; + +static char sb_terminal[] = { IAC, SB, + TELOPT_TTYPE, TELQUAL_IS, + 'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2', + IAC, SE }; +#define SBTERMMODEL 13 + +static int + Sent3270TerminalType; /* Have we said we are a 3270? */ + +#endif /* defined(TN3270) */ + + + void +init_3270() +{ +#if defined(TN3270) +#if defined(unix) || defined(__APPLE__) + HaveInput = 0; + sigiocount = 0; +#endif /* defined(unix) || defined(__APPLE__) */ + Sent3270TerminalType = 0; + Ifrontp = Ibackp = Ibuf; + init_ctlr(); /* Initialize some things */ + init_keyboard(); + init_screen(); + init_system(); +#endif /* defined(TN3270) */ +} + + +#if defined(TN3270) + +/* + * DataToNetwork - queue up some data to go to network. If "done" is set, + * then when last byte is queued, we add on an IAC EOR sequence (so, + * don't call us with "done" until you want that done...) + * + * We actually do send all the data to the network buffer, since our + * only client needs for us to do that. + */ + + int +DataToNetwork(buffer, count, done) + register char *buffer; /* where the data is */ + register int count; /* how much to send */ + int done; /* is this the last of a logical block */ +{ + register int loop, c; + int origCount; + + origCount = count; + + while (count) { + /* If not enough room for EORs, IACs, etc., wait */ + if (NETROOM() < 6) { + fd_set o; + + FD_ZERO(&o); + netflush(); + while (NETROOM() < 6) { + FD_SET(net, &o); + (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0, + (struct timeval *) 0); + netflush(); + } + } + c = ring_empty_count(&netoring); + if (c > count) { + c = count; + } + loop = c; + while (loop) { + if (((unsigned char)*buffer) == IAC) { + break; + } + buffer++; + loop--; + } + if ((c = c-loop)) { + ring_supply_data(&netoring, buffer-c, c); + count -= c; + } + if (loop) { + NET2ADD(IAC, IAC); + count--; + buffer++; + } + } + + if (done) { + NET2ADD(IAC, EOR); + netflush(); /* try to move along as quickly as ... */ + } + return(origCount - count); +} + + +#if defined(unix) || defined(__APPLE__) + void +inputAvailable(signo) + int signo; +{ + HaveInput = 1; + sigiocount++; +} +#endif /* defined(unix) || defined(__APPLE__) */ + + void +outputPurge() +{ + (void) ttyflush(1); +} + + +/* + * The following routines are places where the various tn3270 + * routines make calls into telnet.c. + */ + +/* + * DataToTerminal - queue up some data to go to terminal. + * + * Note: there are people who call us and depend on our processing + * *all* the data at one time (thus the select). + */ + + int +DataToTerminal(buffer, count) + register char *buffer; /* where the data is */ + register int count; /* how much to send */ +{ + register int c; + int origCount; + + origCount = count; + + while (count) { + if (TTYROOM() == 0) { +#if defined(unix) || defined(__APPLE__) + fd_set o; + + FD_ZERO(&o); +#endif /* defined(unix) || defined(__APPLE__) */ + (void) ttyflush(0); + while (TTYROOM() == 0) { +#if defined(unix) || defined(__APPLE__) + FD_SET(tout, &o); + (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, + (struct timeval *) 0); +#endif /* defined(unix) || defined(__APPLE__) */ + (void) ttyflush(0); + } + } + c = TTYROOM(); + if (c > count) { + c = count; + } + ring_supply_data(&ttyoring, buffer, c); + count -= c; + buffer += c; + } + return(origCount); +} + + +/* + * Push3270 - Try to send data along the 3270 output (to screen) direction. + */ + + int +Push3270() +{ + int save = ring_full_count(&netiring); + + if (save) { + if (Ifrontp+save > Ibuf+sizeof Ibuf) { + if (Ibackp != Ibuf) { + memmove(Ibuf, Ibackp, Ifrontp-Ibackp); + Ifrontp -= (Ibackp-Ibuf); + Ibackp = Ibuf; + } + } + if (Ifrontp+save < Ibuf+sizeof Ibuf) { + (void)telrcv(); + } + } + return save != ring_full_count(&netiring); +} + + +/* + * Finish3270 - get the last dregs of 3270 data out to the terminal + * before quitting. + */ + + void +Finish3270() +{ + while (Push3270() || !DoTerminalOutput()) { +#if defined(unix) || defined(__APPLE__) + HaveInput = 0; +#endif /* defined(unix) || defined(__APPLE__) */ + ; + } +} + + +/* StringToTerminal - output a null terminated string to the terminal */ + + void +StringToTerminal(s) + char *s; +{ + int count; + + count = strlen(s); + if (count) { + (void) DataToTerminal(s, count); /* we know it always goes... */ + } +} + + +#if ((!defined(NOT43)) || defined(PUTCHAR)) +/* _putchar - output a single character to the terminal. This name is so that + * curses(3x) can call us to send out data. + */ + + void +_putchar(c) + char c; +{ +#if defined(sun) /* SunOS 4.0 bug */ + c &= 0x7f; +#endif /* defined(sun) */ + if (cursesdata) { + Dump('>', &c, 1); + } + if (!TTYROOM()) { + (void) DataToTerminal(&c, 1); + } else { + TTYADD(c); + } +} +#endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */ + + void +SetIn3270() +{ + if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY) + && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) { + if (!In3270) { + In3270 = 1; + Init3270(); /* Initialize 3270 functions */ + /* initialize terminal key mapping */ + InitTerminal(); /* Start terminal going */ + setconnmode(0); + } + } else { + if (In3270) { + StopScreen(1); + In3270 = 0; + Stop3270(); /* Tell 3270 we aren't here anymore */ + setconnmode(0); + } + } +} + +/* + * tn3270_ttype() + * + * Send a response to a terminal type negotiation. + * + * Return '0' if no more responses to send; '1' if a response sent. + */ + + int +tn3270_ttype() +{ + /* + * Try to send a 3270 type terminal name. Decide which one based + * on the format of our screen, and (in the future) color + * capaiblities. + */ + InitTerminal(); /* Sets MaxNumberColumns, MaxNumberLines */ + if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) { + Sent3270TerminalType = 1; + if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) { + MaxNumberLines = 27; + MaxNumberColumns = 132; + sb_terminal[SBTERMMODEL] = '5'; + } else if (MaxNumberLines >= 43) { + MaxNumberLines = 43; + MaxNumberColumns = 80; + sb_terminal[SBTERMMODEL] = '4'; + } else if (MaxNumberLines >= 32) { + MaxNumberLines = 32; + MaxNumberColumns = 80; + sb_terminal[SBTERMMODEL] = '3'; + } else { + MaxNumberLines = 24; + MaxNumberColumns = 80; + sb_terminal[SBTERMMODEL] = '2'; + } + NumberLines = 24; /* before we start out... */ + NumberColumns = 80; + ScreenSize = NumberLines*NumberColumns; + if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) { + ExitString("Programming error: MAXSCREENSIZE too small.\n", + 1); + /*NOTREACHED*/ + } + printsub('>', sb_terminal+2, sizeof sb_terminal-2); + ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal); + return 1; + } else { + return 0; + } +} + +#if defined(unix) || defined(__APPLE__) + int +settranscom(argc, argv) + int argc; + char *argv[]; +{ + int i; + + if (argc == 1 && transcom) { + transcom = 0; + } + if (argc == 1) { + return 1; + } + transcom = tline; + (void) strcpy(transcom, argv[1]); + for (i = 2; i < argc; ++i) { + (void) strcat(transcom, " "); + (void) strcat(transcom, argv[i]); + } + return 1; +} +#endif /* defined(unix) || defined(__APPLE__) */ + +#endif /* defined(TN3270) */ diff --git a/telnet.tproj/types.h b/telnet.tproj/types.h new file mode 100644 index 0000000..42b1b8f --- /dev/null +++ b/telnet.tproj/types.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)types.h 8.1 (Berkeley) 6/6/93 + */ + +typedef struct { + char *modedescriptions; + char modetype; +} Modelist; + +extern Modelist modelist[]; + +typedef struct { + int + system, /* what the current time is */ + echotoggle, /* last time user entered echo character */ + modenegotiated, /* last time operating mode negotiated */ + didnetreceive, /* last time we read data from network */ + gotDM; /* when did we last see a data mark */ +} Clocks; + +extern Clocks clocks; diff --git a/telnet.tproj/utilities.c b/telnet.tproj/utilities.c new file mode 100644 index 0000000..2957297 --- /dev/null +++ b/telnet.tproj/utilities.c @@ -0,0 +1,962 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#define TELOPTS +#define TELCMDS +#define SLC_NAMES +#include +#include +#include + +#include + +#include "general.h" + +#include "fdset.h" + +#include "ring.h" + +#include "defines.h" + +#include "externs.h" + +FILE *NetTrace = 0; /* Not in bss, since needs to stay */ +int prettydump; + +/* + * upcase() + * + * Upcase (in place) the argument. + */ + + void +upcase(argument) + register char *argument; +{ + register int c; + + while ((c = *argument) != 0) { + if (islower(c)) { + *argument = toupper(c); + } + argument++; + } +} + +/* + * SetSockOpt() + * + * Compensate for differences in 4.2 and 4.3 systems. + */ + + int +SetSockOpt(fd, level, option, yesno) + int fd, level, option, yesno; +{ +#ifndef NOT43 + return setsockopt(fd, level, option, + (char *)&yesno, sizeof yesno); +#else /* NOT43 */ + if (yesno == 0) { /* Can't do that in 4.2! */ + fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", + option); + return -1; + } + return setsockopt(fd, level, option, 0, 0); +#endif /* NOT43 */ +} + +/* + * The following are routines used to print out debugging information. + */ + +unsigned char NetTraceFile[256] = "(standard output)"; + + void +SetNetTrace(file) + register char *file; +{ + if (NetTrace && NetTrace != stdout) + fclose(NetTrace); + if (file && (strcmp(file, "-") != 0)) { + NetTrace = fopen(file, "w"); + if (NetTrace) { + strcpy((char *)NetTraceFile, file); + return; + } + fprintf(stderr, "Cannot open %s.\n", file); + } + NetTrace = stdout; + strcpy((char *)NetTraceFile, "(standard output)"); +} + + void +Dump(direction, buffer, length) + char direction; + unsigned char *buffer; + int length; +{ +# define BYTES_PER_LINE 32 +# define min(x,y) ((x' */ + unsigned char *pointer; /* where suboption data sits */ + int length; /* length of suboption data */ +{ + register int i; + char buf[512]; + extern int want_status_response; + + if (showoptions || direction == 0 || + (want_status_response && (pointer[0] == TELOPT_STATUS))) { + if (direction) { + fprintf(NetTrace, "%s IAC SB ", + (direction == '<')? "RCVD":"SENT"); + if (length >= 3) { + register int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if (i != IAC || j != SE) { + fprintf(NetTrace, "(terminated by "); + if (TELOPT_OK(i)) + fprintf(NetTrace, "%s ", TELOPT(i)); + else if (TELCMD_OK(i)) + fprintf(NetTrace, "%s ", TELCMD(i)); + else + fprintf(NetTrace, "%d ", i); + if (TELOPT_OK(j)) + fprintf(NetTrace, "%s", TELOPT(j)); + else if (TELCMD_OK(j)) + fprintf(NetTrace, "%s", TELCMD(j)); + else + fprintf(NetTrace, "%d", j); + fprintf(NetTrace, ", not IAC SE!) "); + } + } + length -= 2; + } + if (length < 1) { + fprintf(NetTrace, "(Empty suboption??\?)"); + if (NetTrace == stdout) + fflush(NetTrace); + return; + } + switch (pointer[0]) { + case TELOPT_TTYPE: + fprintf(NetTrace, "TERMINAL-TYPE "); + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); + break; + case TELQUAL_SEND: + fprintf(NetTrace, "SEND"); + break; + default: + fprintf(NetTrace, + "- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + case TELOPT_TSPEED: + fprintf(NetTrace, "TERMINAL-SPEED"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, " IS "); + fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); + break; + default: + if (pointer[1] == 1) + fprintf(NetTrace, " SEND"); + else + fprintf(NetTrace, " %d (unknown)", pointer[1]); + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + } + break; + + case TELOPT_LFLOW: + fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case LFLOW_OFF: + fprintf(NetTrace, " OFF"); break; + case LFLOW_ON: + fprintf(NetTrace, " ON"); break; + case LFLOW_RESTART_ANY: + fprintf(NetTrace, " RESTART-ANY"); break; + case LFLOW_RESTART_XON: + fprintf(NetTrace, " RESTART-XON"); break; + default: + fprintf(NetTrace, " %d (unknown)", pointer[1]); + } + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + + case TELOPT_NAWS: + fprintf(NetTrace, "NAWS"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + if (length == 2) { + fprintf(NetTrace, " ?%d?", pointer[1]); + break; + } + fprintf(NetTrace, " %d %d (%d)", + pointer[1], pointer[2], + (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); + if (length == 4) { + fprintf(NetTrace, " ?%d?", pointer[3]); + break; + } + fprintf(NetTrace, " %d %d (%d)", + pointer[3], pointer[4], + (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); + for (i = 5; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + fprintf(NetTrace, "AUTHENTICATION"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case TELQUAL_REPLY: + case TELQUAL_IS: + fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? + "IS" : "REPLY"); + if (AUTHTYPE_NAME_OK(pointer[2])) + fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); + else + fprintf(NetTrace, "%d ", pointer[2]); + if (length < 3) { + fprintf(NetTrace, "(partial suboption??\?)"); + break; + } + fprintf(NetTrace, "%s|%s", + ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + + auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + fprintf(NetTrace, "%s", buf); + break; + + case TELQUAL_SEND: + i = 2; + fprintf(NetTrace, " SEND "); + while (i < length) { + if (AUTHTYPE_NAME_OK(pointer[i])) + fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); + else + fprintf(NetTrace, "%d ", pointer[i]); + if (++i >= length) { + fprintf(NetTrace, "(partial suboption??\?)"); + break; + } + fprintf(NetTrace, "%s|%s ", + ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + ++i; + } + break; + + case TELQUAL_NAME: + i = 2; + fprintf(NetTrace, " NAME \""); + while (i < length) + putc(pointer[i++], NetTrace); + putc('"', NetTrace); + break; + + default: + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + } + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + fprintf(NetTrace, "ENCRYPT"); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case ENCRYPT_START: + fprintf(NetTrace, " START"); + break; + + case ENCRYPT_END: + fprintf(NetTrace, " END"); + break; + + case ENCRYPT_REQSTART: + fprintf(NetTrace, " REQUEST-START"); + break; + + case ENCRYPT_REQEND: + fprintf(NetTrace, " REQUEST-END"); + break; + + case ENCRYPT_IS: + case ENCRYPT_REPLY: + fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? + "IS" : "REPLY"); + if (length < 3) { + fprintf(NetTrace, " (partial suboption??\?)"); + break; + } + if (ENCTYPE_NAME_OK(pointer[2])) + fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); + else + fprintf(NetTrace, " %d (unknown)", pointer[2]); + + encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + fprintf(NetTrace, "%s", buf); + break; + + case ENCRYPT_SUPPORT: + i = 2; + fprintf(NetTrace, " SUPPORT "); + while (i < length) { + if (ENCTYPE_NAME_OK(pointer[i])) + fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); + else + fprintf(NetTrace, "%d ", pointer[i]); + i++; + } + break; + + case ENCRYPT_ENC_KEYID: + fprintf(NetTrace, " ENC_KEYID "); + goto encommon; + + case ENCRYPT_DEC_KEYID: + fprintf(NetTrace, " DEC_KEYID "); + goto encommon; + + default: + fprintf(NetTrace, " %d (unknown)", pointer[1]); + encommon: + for (i = 2; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + break; + } + break; +#endif /* ENCRYPTION */ + + case TELOPT_LINEMODE: + fprintf(NetTrace, "LINEMODE "); + if (length < 2) { + fprintf(NetTrace, " (empty suboption??\?)"); + break; + } + switch (pointer[1]) { + case WILL: + fprintf(NetTrace, "WILL "); + goto common; + case WONT: + fprintf(NetTrace, "WONT "); + goto common; + case DO: + fprintf(NetTrace, "DO "); + goto common; + case DONT: + fprintf(NetTrace, "DONT "); + common: + if (length < 3) { + fprintf(NetTrace, "(no option??\?)"); + break; + } + switch (pointer[2]) { + case LM_FORWARDMASK: + fprintf(NetTrace, "Forward Mask"); + for (i = 3; i < length; i++) + fprintf(NetTrace, " %x", pointer[i]); + break; + default: + fprintf(NetTrace, "%d (unknown)", pointer[2]); + for (i = 3; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + break; + } + break; + + case LM_SLC: + fprintf(NetTrace, "SLC"); + for (i = 2; i < length - 2; i += 3) { + if (SLC_NAME_OK(pointer[i+SLC_FUNC])) + fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); + else + fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); + switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { + case SLC_NOSUPPORT: + fprintf(NetTrace, " NOSUPPORT"); break; + case SLC_CANTCHANGE: + fprintf(NetTrace, " CANTCHANGE"); break; + case SLC_VARIABLE: + fprintf(NetTrace, " VARIABLE"); break; + case SLC_DEFAULT: + fprintf(NetTrace, " DEFAULT"); break; + } + fprintf(NetTrace, "%s%s%s", + pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); + if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| + SLC_FLUSHOUT| SLC_LEVELBITS)) + fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); + fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); + if ((pointer[i+SLC_VALUE] == IAC) && + (pointer[i+SLC_VALUE+1] == IAC)) + i++; + } + for (; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + + case LM_MODE: + fprintf(NetTrace, "MODE "); + if (length < 3) { + fprintf(NetTrace, "(no mode??\?)"); + break; + } + { + char tbuf[64]; + sprintf(tbuf, "%s%s%s%s%s", + pointer[2]&MODE_EDIT ? "|EDIT" : "", + pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", + pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", + pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", + pointer[2]&MODE_ACK ? "|ACK" : ""); + fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); + } + if (pointer[2]&~(MODE_MASK)) + fprintf(NetTrace, " (0x%x)", pointer[2]); + for (i = 3; i < length; i++) + fprintf(NetTrace, " ?0x%x?", pointer[i]); + break; + default: + fprintf(NetTrace, "%d (unknown)", pointer[1]); + for (i = 2; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + } + break; + + case TELOPT_STATUS: { + register char *cp; + register int j, k; + + fprintf(NetTrace, "STATUS"); + + switch (pointer[1]) { + default: + if (pointer[1] == TELQUAL_SEND) + fprintf(NetTrace, " SEND"); + else + fprintf(NetTrace, " %d (unknown)", pointer[1]); + for (i = 2; i < length; i++) + fprintf(NetTrace, " ?%d?", pointer[i]); + break; + case TELQUAL_IS: + if (--want_status_response < 0) + want_status_response = 0; + if (NetTrace == stdout) + fprintf(NetTrace, " IS\r\n"); + else + fprintf(NetTrace, " IS\n"); + + for (i = 2; i < length; i++) { + switch(pointer[i]) { + case DO: cp = "DO"; goto common2; + case DONT: cp = "DONT"; goto common2; + case WILL: cp = "WILL"; goto common2; + case WONT: cp = "WONT"; goto common2; + common2: + i++; + if (TELOPT_OK((int)pointer[i])) + fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); + else + fprintf(NetTrace, " %s %d", cp, pointer[i]); + + if (NetTrace == stdout) + fprintf(NetTrace, "\r\n"); + else + fprintf(NetTrace, "\n"); + break; + + case SB: + fprintf(NetTrace, " SB "); + i++; + j = k = i; + while (j < length) { + if (pointer[j] == SE) { + if (j+1 == length) + break; + if (pointer[j+1] == SE) + j++; + else + break; + } + pointer[k++] = pointer[j++]; + } + printsub(0, &pointer[i], k - i); + if (i < length) { + fprintf(NetTrace, " SE"); + i = j; + } else + i = j - 1; + + if (NetTrace == stdout) + fprintf(NetTrace, "\r\n"); + else + fprintf(NetTrace, "\n"); + + break; + + default: + fprintf(NetTrace, " %d", pointer[i]); + break; + } + } + break; + } + break; + } + + case TELOPT_XDISPLOC: + fprintf(NetTrace, "X-DISPLAY-LOCATION "); + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); + break; + case TELQUAL_SEND: + fprintf(NetTrace, "SEND"); + break; + default: + fprintf(NetTrace, "- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + break; + + case TELOPT_NEW_ENVIRON: + fprintf(NetTrace, "NEW-ENVIRON "); +#ifdef OLD_ENVIRON + goto env_common1; + case TELOPT_OLD_ENVIRON: + fprintf(NetTrace, "OLD-ENVIRON"); + env_common1: +#endif + switch (pointer[1]) { + case TELQUAL_IS: + fprintf(NetTrace, "IS "); + goto env_common; + case TELQUAL_SEND: + fprintf(NetTrace, "SEND "); + goto env_common; + case TELQUAL_INFO: + fprintf(NetTrace, "INFO "); + env_common: + { + register int noquote = 2; +#if defined(ENV_HACK) && defined(OLD_ENVIRON) + extern int old_env_var, old_env_value; +#endif + for (i = 2; i < length; i++ ) { + switch (pointer[i]) { + case NEW_ENV_VALUE: +#ifdef OLD_ENVIRON + /* case NEW_ENV_OVAR: */ + if (pointer[0] == TELOPT_OLD_ENVIRON) { +# ifdef ENV_HACK + if (old_env_var == OLD_ENV_VALUE) + fprintf(NetTrace, "\" (VALUE) " + noquote); + else +# endif + fprintf(NetTrace, "\" VAR " + noquote); + } else +#endif /* OLD_ENVIRON */ + fprintf(NetTrace, "\" VALUE " + noquote); + noquote = 2; + break; + + case NEW_ENV_VAR: +#ifdef OLD_ENVIRON + /* case OLD_ENV_VALUE: */ + if (pointer[0] == TELOPT_OLD_ENVIRON) { +# ifdef ENV_HACK + if (old_env_value == OLD_ENV_VAR) + fprintf(NetTrace, "\" (VAR) " + noquote); + else +# endif + fprintf(NetTrace, "\" VALUE " + noquote); + } else +#endif /* OLD_ENVIRON */ + fprintf(NetTrace, "\" VAR " + noquote); + noquote = 2; + break; + + case ENV_ESC: + fprintf(NetTrace, "\" ESC " + noquote); + noquote = 2; + break; + + case ENV_USERVAR: + fprintf(NetTrace, "\" USERVAR " + noquote); + noquote = 2; + break; + + default: + def_case: + if (isprint(pointer[i]) && pointer[i] != '"') { + if (noquote) { + putc('"', NetTrace); + noquote = 0; + } + putc(pointer[i], NetTrace); + } else { + fprintf(NetTrace, "\" %03o " + noquote, + pointer[i]); + noquote = 2; + } + break; + } + } + if (!noquote) + putc('"', NetTrace); + break; + } + } + break; + + default: + if (TELOPT_OK(pointer[0])) + fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); + else + fprintf(NetTrace, "%d (unknown)", pointer[0]); + for (i = 1; i < length; i++) + fprintf(NetTrace, " %d", pointer[i]); + break; + } + if (direction) { + if (NetTrace == stdout) + fprintf(NetTrace, "\r\n"); + else + fprintf(NetTrace, "\n"); + } + if (NetTrace == stdout) + fflush(NetTrace); + } +} + +/* EmptyTerminal - called to make sure that the terminal buffer is empty. + * Note that we consider the buffer to run all the + * way to the kernel (thus the select). + */ + + void +EmptyTerminal() +{ +#if defined(unix) || defined(__APPLE__) + fd_set o; + + FD_ZERO(&o); +#endif /* defined(unix) || defined(__APPLE__) */ + + if (TTYBYTES() == 0) { +#if defined(unix) || defined(__APPLE__) + FD_SET(tout, &o); + (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, + (struct timeval *) 0); /* wait for TTLOWAT */ +#endif /* defined(unix) || defined(__APPLE__) */ + } else { + while (TTYBYTES()) { + (void) ttyflush(0); +#if defined(unix) || defined(__APPLE__) + FD_SET(tout, &o); + (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, + (struct timeval *) 0); /* wait for TTLOWAT */ +#endif /* defined(unix) || defined(__APPLE__) */ + } + } +} + + void +SetForExit() +{ + setconnmode(0); +#if defined(TN3270) + if (In3270) { + Finish3270(); + } +#else /* defined(TN3270) */ + do { + (void)telrcv(); /* Process any incoming data */ + EmptyTerminal(); + } while (ring_full_count(&netiring)); /* While there is any */ +#endif /* defined(TN3270) */ + setcommandmode(); + fflush(stdout); + fflush(stderr); +#if defined(TN3270) + if (In3270) { + StopScreen(1); + } +#endif /* defined(TN3270) */ + setconnmode(0); + EmptyTerminal(); /* Flush the path to the tty */ + setcommandmode(); +} + + void +Exit(returnCode) + int returnCode; +{ + SetForExit(); + exit(returnCode); +} + + void +ExitString(string, returnCode) + char *string; + int returnCode; +{ + SetForExit(); + fwrite(string, 1, strlen(string), stderr); + exit(returnCode); +} diff --git a/telnetd.tproj/Makefile b/telnetd.tproj/Makefile new file mode 100644 index 0000000..63a671f --- /dev/null +++ b/telnetd.tproj/Makefile @@ -0,0 +1,56 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = telnetd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = defs.h ext.h pathnames.h telnetd.h + +CFILES = authenc.c global.c slc.c state.c sys_term.c telnetd.c\ + termstat.c utility.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble telnetd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +NEXTSTEP_PB_CFLAGS = -DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION +WINDOWS_PB_CFLAGS = -DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION +PDO_UNIX_PB_CFLAGS = -DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/telnetd.tproj/Makefile.postamble b/telnetd.tproj/Makefile.postamble new file mode 100644 index 0000000..7ede358 --- /dev/null +++ b/telnetd.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/telnetd.tproj/Makefile.preamble b/telnetd.tproj/Makefile.preamble new file mode 100644 index 0000000..70aa1d8 --- /dev/null +++ b/telnetd.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = -ltelnet +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +-include ../Makefile.include diff --git a/telnetd.tproj/PB.project b/telnetd.tproj/PB.project new file mode 100644 index 0000000..8dfbe1c --- /dev/null +++ b/telnetd.tproj/PB.project @@ -0,0 +1,50 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (defs.h, ext.h, pathnames.h, telnetd.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = ( + authenc.c, + global.c, + slc.c, + state.c, + sys_term.c, + telnetd.c, + termstat.c, + utility.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, telnetd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_COMPILEROPTIONS = "-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION"; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = "-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION"; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = telnetd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = "-DLINEMODE -DKLUDGELINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK # -DAUTHENTICATION -DENCRYPTION"; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/telnetd.tproj/authenc.c b/telnetd.tproj/authenc.c new file mode 100644 index 0000000..7891835 --- /dev/null +++ b/telnetd.tproj/authenc.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)authenc.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) +#include "telnetd.h" +#include + + int +net_write(str, len) + unsigned char *str; + int len; +{ + if (nfrontp + len < netobuf + BUFSIZ) { + memmove((void *)nfrontp, (void *)str, len); + nfrontp += len; + return(len); + } + return(0); +} + + void +net_encrypt() +{ +#ifdef ENCRYPTION + char *s = (nclearto > nbackp) ? nclearto : nbackp; + if (s < nfrontp && encrypt_output) { + (*encrypt_output)((unsigned char *)s, nfrontp - s); + } + nclearto = nfrontp; +#endif /* ENCRYPTION */ +} + + int +telnet_spin() +{ + ttloop(); + return(0); +} + + char * +telnet_getenv(val) + char *val; +{ + extern char *getenv(); + return(getenv(val)); +} + + char * +telnet_gets(prompt, result, length, echo) + char *prompt; + char *result; + int length; + int echo; +{ + return((char *)0); +} +#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ diff --git a/telnetd.tproj/defs.h b/telnetd.tproj/defs.h new file mode 100644 index 0000000..1224895 --- /dev/null +++ b/telnetd.tproj/defs.h @@ -0,0 +1,323 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)defs.h 8.1 (Berkeley) 6/4/93 + */ + +/* + * Telnet server defines + */ +#include +#include + +#ifndef BSD +# define BSD 43 +#endif + +#if defined(CRAY) && !defined(LINEMODE) +# define SYSV_TERMIO +# define LINEMODE +# define KLUDGELINEMODE +# define DIAGNOSTICS +# if defined(UNICOS50) && !defined(UNICOS5) +# define UNICOS5 +# endif +# if !defined(UNICOS5) +# define BFTPDAEMON +# define HAS_IP_TOS +# endif +#endif /* CRAY */ +#if defined(UNICOS5) && !defined(NO_SETSID) +# define NO_SETSID +#endif + +#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS) +#define TELOPTS +#define TELCMDS +#define SLC_NAMES +#endif + +#if defined(SYSV_TERMIO) && !defined(USE_TERMIO) +# define USE_TERMIO +#endif + +#include +#ifndef CRAY +#include +#endif /* CRAY */ +#include +#include +#include +#include +#ifndef FILIO_H +#include +#else +#include +#endif + +#include + +#include + +#include +#ifdef __STDC__ +#include +#endif +#include +#include +#include +#include +#ifndef LOG_DAEMON +#define LOG_DAEMON 0 +#endif +#ifndef LOG_ODELAY +#define LOG_ODELAY 0 +#endif +#include +#ifndef NO_STRING_H +#include +#else +#include +#endif + +#ifndef USE_TERMIO +#include +#else +# ifdef SYSV_TERMIO +# include +# else +# ifdef __APPLE__ +# include +# else +# include +# endif +# endif +#endif +#if !defined(USE_TERMIO) || defined(NO_CC_T) +typedef unsigned char cc_t; +#endif + +#ifdef __STDC__ +#include +#endif + +#ifndef _POSIX_VDISABLE +# ifdef VDISABLE +# define _POSIX_VDISABLE VDISABLE +# else +# define _POSIX_VDISABLE ((unsigned char)'\377') +# endif +#endif + + +#ifdef CRAY +# ifdef CRAY1 +# include +# ifndef FD_ZERO +# include +# endif /* FD_ZERO */ +# endif /* CRAY1 */ + +#include +#endif /* CRAY */ + +#ifdef __hpux +#include +#endif + +#if !defined(TIOCSCTTY) && defined(TCSETCTTY) +# define TIOCSCTTY TCSETCTTY +#endif + +#ifndef FD_SET +#ifndef HAVE_fd_set +typedef struct fd_set { int fds_bits[1]; } fd_set; +#endif + +#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) +#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) +#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) +#define FD_ZERO(p) ((p)->fds_bits[0] = 0) +#endif /* FD_SET */ + +/* + * I/O data buffers defines + */ +#define NETSLOP 64 +#ifdef CRAY +#undef BUFSIZ +#define BUFSIZ 2048 +#endif + +#define NIACCUM(c) { *netip++ = c; \ + ncc++; \ + } + +/* clock manipulations */ +#define settimer(x) (clocks.x = ++clocks.system) +#define sequenceIs(x,y) (clocks.x < clocks.y) + +/* + * Linemode support states, in decreasing order of importance + */ +#define REAL_LINEMODE 0x04 +#define KLUDGE_OK 0x03 +#define NO_AUTOKLUDGE 0x02 +#define KLUDGE_LINEMODE 0x01 +#define NO_LINEMODE 0x00 + +/* + * Structures of information for each special character function. + */ +typedef struct { + unsigned char flag; /* the flags for this function */ + cc_t val; /* the value of the special character */ +} slcent, *Slcent; + +typedef struct { + slcent defset; /* the default settings */ + slcent current; /* the current settings */ + cc_t *sptr; /* a pointer to the char in */ + /* system data structures */ +} slcfun, *Slcfun; + +#ifdef DIAGNOSTICS +/* + * Diagnostics capabilities + */ +#define TD_REPORT 0x01 /* Report operations to client */ +#define TD_EXERCISE 0x02 /* Exercise client's implementation */ +#define TD_NETDATA 0x04 /* Display received data stream */ +#define TD_PTYDATA 0x08 /* Display data passed to pty */ +#define TD_OPTIONS 0x10 /* Report just telnet options */ +#endif /* DIAGNOSTICS */ + +/* + * We keep track of each side of the option negotiation. + */ + +#define MY_STATE_WILL 0x01 +#define MY_WANT_STATE_WILL 0x02 +#define MY_STATE_DO 0x04 +#define MY_WANT_STATE_DO 0x08 + +/* + * Macros to check the current state of things + */ + +#define my_state_is_do(opt) (options[opt]&MY_STATE_DO) +#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) +#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) +#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) + +#define my_state_is_dont(opt) (!my_state_is_do(opt)) +#define my_state_is_wont(opt) (!my_state_is_will(opt)) +#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) +#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) + +#define set_my_state_do(opt) (options[opt] |= MY_STATE_DO) +#define set_my_state_will(opt) (options[opt] |= MY_STATE_WILL) +#define set_my_want_state_do(opt) (options[opt] |= MY_WANT_STATE_DO) +#define set_my_want_state_will(opt) (options[opt] |= MY_WANT_STATE_WILL) + +#define set_my_state_dont(opt) (options[opt] &= ~MY_STATE_DO) +#define set_my_state_wont(opt) (options[opt] &= ~MY_STATE_WILL) +#define set_my_want_state_dont(opt) (options[opt] &= ~MY_WANT_STATE_DO) +#define set_my_want_state_wont(opt) (options[opt] &= ~MY_WANT_STATE_WILL) + +/* + * Tricky code here. What we want to know is if the MY_STATE_WILL + * and MY_WANT_STATE_WILL bits have the same value. Since the two + * bits are adjacent, a little arithmatic will show that by adding + * in the lower bit, the upper bit will be set if the two bits were + * different, and clear if they were the same. + */ +#define my_will_wont_is_changing(opt) \ + ((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL) + +#define my_do_dont_is_changing(opt) \ + ((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO) + +/* + * Make everything symetrical + */ + +#define HIS_STATE_WILL MY_STATE_DO +#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO +#define HIS_STATE_DO MY_STATE_WILL +#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL + +#define his_state_is_do my_state_is_will +#define his_state_is_will my_state_is_do +#define his_want_state_is_do my_want_state_is_will +#define his_want_state_is_will my_want_state_is_do + +#define his_state_is_dont my_state_is_wont +#define his_state_is_wont my_state_is_dont +#define his_want_state_is_dont my_want_state_is_wont +#define his_want_state_is_wont my_want_state_is_dont + +#define set_his_state_do set_my_state_will +#define set_his_state_will set_my_state_do +#define set_his_want_state_do set_my_want_state_will +#define set_his_want_state_will set_my_want_state_do + +#define set_his_state_dont set_my_state_wont +#define set_his_state_wont set_my_state_dont +#define set_his_want_state_dont set_my_want_state_wont +#define set_his_want_state_wont set_my_want_state_dont + +#define his_will_wont_is_changing my_do_dont_is_changing +#define his_do_dont_is_changing my_will_wont_is_changing diff --git a/telnetd.tproj/ext.h b/telnetd.tproj/ext.h new file mode 100644 index 0000000..18ab636 --- /dev/null +++ b/telnetd.tproj/ext.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)ext.h 8.2 (Berkeley) 12/15/93 + */ + +/* + * Telnet server variable declarations + */ +extern char options[256]; +extern char do_dont_resp[256]; +extern char will_wont_resp[256]; +extern int linemode; /* linemode on/off */ +#ifdef LINEMODE +extern int uselinemode; /* what linemode to use (on/off) */ +extern int editmode; /* edit modes in use */ +extern int useeditmode; /* edit modes to use */ +extern int alwayslinemode; /* command line option */ +# ifdef KLUDGELINEMODE +extern int lmodetype; /* Client support for linemode */ +# endif /* KLUDGELINEMODE */ +#endif /* LINEMODE */ +extern int flowmode; /* current flow control state */ +extern int restartany; /* restart output on any character state */ +#ifdef DIAGNOSTICS +extern int diagnostic; /* telnet diagnostic capabilities */ +#endif /* DIAGNOSTICS */ +#ifdef BFTPDAEMON +extern int bftpd; /* behave as bftp daemon */ +#endif /* BFTPDAEMON */ +#if defined(SecurID) +extern int require_SecurID; +#endif +#if defined(AUTHENTICATION) +extern int auth_level; +#endif + +extern slcfun slctab[NSLC + 1]; /* slc mapping table */ + +extern char *terminaltype; + +/* + * I/O data buffers, pointers, and counters. + */ +extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; + +extern char netibuf[BUFSIZ], *netip; + +extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; +extern char *neturg; /* one past last bye of urgent data */ + +extern int pcc, ncc; + +#if defined(CRAY2) && defined(UNICOS5) +extern int unpcc; /* characters left unprocessed by CRAY-2 terminal routine */ +extern char *unptyip; /* pointer to remaining characters in buffer */ +#endif + +extern int pty, net; +#ifdef __APPLE__ +extern char line[16]; +#else +extern char *line; +#endif /* !NeXT */ +extern int SYNCHing; /* we are in TELNET SYNCH mode */ + +#ifndef P +# ifdef __STDC__ +# define P(x) x +# else +# define P(x) () +# endif +#endif + +extern void + _termstat P((void)), + add_slc P((int, int, int)), + check_slc P((void)), + change_slc P((int, int, int)), + cleanup P((int)), + clientstat P((int, int, int)), + copy_termbuf P((char *, int)), + deferslc P((void)), + defer_terminit P((void)), + do_opt_slc P((unsigned char *, int)), + doeof P((void)), + dooption P((int)), + dontoption P((int)), + edithost P((char *, char *)), + fatal P((int, char *)), + fatalperror P((int, char *)), + get_slc_defaults P((void)), + init_env P((void)), + init_termbuf P((void)), + interrupt P((void)), + localstat P((void)), + flowstat P((void)), + netclear P((void)), + netflush P((void)), +#ifdef DIAGNOSTICS + printoption P((char *, int)), + printdata P((char *, char *, int)), + printsub P((int, unsigned char *, int)), +#endif + ptyflush P((void)), + putchr P((int)), + putf P((char *, char *)), + recv_ayt P((void)), + send_do P((int, int)), + send_dont P((int, int)), + send_slc P((void)), + send_status P((void)), + send_will P((int, int)), + send_wont P((int, int)), + sendbrk P((void)), + sendsusp P((void)), + set_termbuf P((void)), + start_login P((char *, int, char *)), + start_slc P((int)), +#if defined(AUTHENTICATION) + start_slave P((char *)), +#else + start_slave P((char *, int, char *)), +#endif + suboption P((void)), + telrcv P((void)), + ttloop P((void)), + tty_binaryin P((int)), + tty_binaryout P((int)); + +extern int + end_slc P((unsigned char **)), + getnpty P((void)), +#ifndef convex + getpty P((int *)), +#endif + login_tty P((int)), + spcset P((int, cc_t *, cc_t **)), + stilloob P((int)), + terminit P((void)), + termstat P((void)), + tty_flowmode P((void)), + tty_restartany P((void)), + tty_isbinaryin P((void)), + tty_isbinaryout P((void)), + tty_iscrnl P((void)), + tty_isecho P((void)), + tty_isediting P((void)), + tty_islitecho P((void)), + tty_isnewmap P((void)), + tty_israw P((void)), + tty_issofttab P((void)), + tty_istrapsig P((void)), + tty_linemode P((void)); + +extern void + tty_rspeed P((int)), + tty_setecho P((int)), + tty_setedit P((int)), + tty_setlinemode P((int)), + tty_setlitecho P((int)), + tty_setsig P((int)), + tty_setsofttab P((int)), + tty_tspeed P((int)), + willoption P((int)), + wontoption P((int)), + writenet P((unsigned char *, int)); + +#ifdef ENCRYPTION +extern void (*encrypt_output) P((unsigned char *, int)); +extern int (*decrypt_input) P((int)); +extern char *nclearto; +#endif /* ENCRYPTION */ + + +/* + * The following are some clocks used to decide how to interpret + * the relationship between various variables. + */ + +extern struct { + int + system, /* what the current time is */ + echotoggle, /* last time user entered echo character */ + modenegotiated, /* last time operating mode negotiated */ + didnetreceive, /* last time we read data from network */ + ttypesubopt, /* ttype subopt is received */ + tspeedsubopt, /* tspeed subopt is received */ + environsubopt, /* environ subopt is received */ + oenvironsubopt, /* old environ subopt is received */ + xdisplocsubopt, /* xdisploc subopt is received */ + baseline, /* time started to do timed action */ + gotDM; /* when did we last see a data mark */ +} clocks; + + +#if defined(CRAY2) && defined(UNICOS5) +extern int needtermstat; +#endif + +#ifndef DEFAULT_IM +# ifdef CRAY +# define DEFAULT_IM "\r\n\r\nCray UNICOS (%h) (%t)\r\n\r\r\n\r" +# else +# ifdef sun +# define DEFAULT_IM "\r\n\r\nSunOS UNIX (%h) (%t)\r\n\r\r\n\r" +# else +# ifdef ultrix +# define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r" +# else +# define DEFAULT_IM "\r\n\r\n4.4 BSD (%h) (%t)\r\n\r\r\n\r" +# endif +# endif +# endif +#endif diff --git a/telnetd.tproj/global.c b/telnetd.tproj/global.c new file mode 100644 index 0000000..ebed4ed --- /dev/null +++ b/telnetd.tproj/global.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)global.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Allocate global variables. We do this + * by including the header file that defines + * them all as externs, but first we define + * the keyword "extern" to be nothing, so that + * we will actually allocate the space. + */ + +#include "defs.h" +#define extern +#include "ext.h" diff --git a/telnetd.tproj/pathnames.h b/telnetd.tproj/pathnames.h new file mode 100644 index 0000000..c9ac41f --- /dev/null +++ b/telnetd.tproj/pathnames.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + */ + +#if BSD > 43 + +# include + +# ifndef _PATH_LOGIN +# define _PATH_LOGIN "/usr/bin/login" +# endif + +#else + +# define _PATH_TTY "/dev/tty" +# ifndef _PATH_LOGIN +# define _PATH_LOGIN "/bin/login" +# endif + +#endif + +#ifdef BFTPDAEMON +#define BFTPPATH "/usr/ucb/bftp" +#endif /* BFTPDAEMON */ diff --git a/telnetd.tproj/slc.c b/telnetd.tproj/slc.c new file mode 100644 index 0000000..a7b280d --- /dev/null +++ b/telnetd.tproj/slc.c @@ -0,0 +1,514 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)slc.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include "telnetd.h" + +#ifdef LINEMODE +/* + * local varibles + */ +static unsigned char *def_slcbuf = (unsigned char *)0; +static int def_slclen = 0; +static int slcchange; /* change to slc is requested */ +static unsigned char *slcptr; /* pointer into slc buffer */ +static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */ + +/* + * send_slc + * + * Write out the current special characters to the client. + */ + void +send_slc() +{ + register int i; + + /* + * Send out list of triplets of special characters + * to client. We only send info on the characters + * that are currently supported. + */ + for (i = 1; i <= NSLC; i++) { + if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) + continue; + add_slc((unsigned char)i, slctab[i].current.flag, + slctab[i].current.val); + } + +} /* end of send_slc */ + +/* + * default_slc + * + * Set pty special characters to all the defaults. + */ + void +default_slc() +{ + register int i; + + for (i = 1; i <= NSLC; i++) { + slctab[i].current.val = slctab[i].defset.val; + if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) + slctab[i].current.flag = SLC_NOSUPPORT; + else + slctab[i].current.flag = slctab[i].defset.flag; + if (slctab[i].sptr) { + *(slctab[i].sptr) = slctab[i].defset.val; + } + } + slcchange = 1; + +} /* end of default_slc */ +#endif /* LINEMODE */ + +/* + * get_slc_defaults + * + * Initialize the slc mapping table. + */ + void +get_slc_defaults() +{ + register int i; + + init_termbuf(); + + for (i = 1; i <= NSLC; i++) { + slctab[i].defset.flag = + spcset(i, &slctab[i].defset.val, &slctab[i].sptr); + slctab[i].current.flag = SLC_NOSUPPORT; + slctab[i].current.val = 0; + } + +} /* end of get_slc_defaults */ + +#ifdef LINEMODE +/* + * add_slc + * + * Add an slc triplet to the slc buffer. + */ + void +add_slc(func, flag, val) + register char func, flag; + register cc_t val; +{ + + if ((*slcptr++ = (unsigned char)func) == 0xff) + *slcptr++ = 0xff; + + if ((*slcptr++ = (unsigned char)flag) == 0xff) + *slcptr++ = 0xff; + + if ((*slcptr++ = (unsigned char)val) == 0xff) + *slcptr++ = 0xff; + +} /* end of add_slc */ + +/* + * start_slc + * + * Get ready to process incoming slc's and respond to them. + * + * The parameter getit is non-zero if it is necessary to grab a copy + * of the terminal control structures. + */ + void +start_slc(getit) + register int getit; +{ + + slcchange = 0; + if (getit) + init_termbuf(); + (void) sprintf((char *)slcbuf, "%c%c%c%c", + IAC, SB, TELOPT_LINEMODE, LM_SLC); + slcptr = slcbuf + 4; + +} /* end of start_slc */ + +/* + * end_slc + * + * Finish up the slc negotiation. If something to send, then send it. + */ + int +end_slc(bufp) + register unsigned char **bufp; +{ + register int len; + void netflush(); + + /* + * If a change has occured, store the new terminal control + * structures back to the terminal driver. + */ + if (slcchange) { + set_termbuf(); + } + + /* + * If the pty state has not yet been fully processed and there is a + * deferred slc request from the client, then do not send any + * sort of slc negotiation now. We will respond to the client's + * request very soon. + */ + if (def_slcbuf && (terminit() == 0)) { + return(0); + } + + if (slcptr > (slcbuf + 4)) { + if (bufp) { + *bufp = &slcbuf[4]; + return(slcptr - slcbuf - 4); + } else { + (void) sprintf((char *)slcptr, "%c%c", IAC, SE); + slcptr += 2; + len = slcptr - slcbuf; + writenet(slcbuf, len); + netflush(); /* force it out immediately */ + DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2);); + } + } + return (0); + +} /* end of end_slc */ + +/* + * process_slc + * + * Figure out what to do about the client's slc + */ + void +process_slc(func, flag, val) + register unsigned char func, flag; + register cc_t val; +{ + register int hislevel, mylevel, ack; + + /* + * Ensure that we know something about this function + */ + if (func > NSLC) { + add_slc(func, SLC_NOSUPPORT, 0); + return; + } + + /* + * Process the special case requests of 0 SLC_DEFAULT 0 + * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't + * worry about whether the value is actually 0 or not. + */ + if (func == 0) { + if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { + default_slc(); + send_slc(); + } else if (flag == SLC_VARIABLE) { + send_slc(); + } + return; + } + + /* + * Appears to be a function that we know something about. So + * get on with it and see what we know. + */ + + hislevel = flag & SLC_LEVELBITS; + mylevel = slctab[func].current.flag & SLC_LEVELBITS; + ack = flag & SLC_ACK; + /* + * ignore the command if: + * the function value and level are the same as what we already have; + * or the level is the same and the ack bit is set + */ + if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { + return; + } else if (ack) { + /* + * If we get here, we got an ack, but the levels don't match. + * This shouldn't happen. If it does, it is probably because + * we have sent two requests to set a variable without getting + * a response between them, and this is the first response. + * So, ignore it, and wait for the next response. + */ + return; + } else { + change_slc(func, flag, val); + } + +} /* end of process_slc */ + +/* + * change_slc + * + * Process a request to change one of our special characters. + * Compare client's request with what we are capable of supporting. + */ + void +change_slc(func, flag, val) + register char func, flag; + register cc_t val; +{ + register int hislevel, mylevel; + + hislevel = flag & SLC_LEVELBITS; + mylevel = slctab[func].defset.flag & SLC_LEVELBITS; + /* + * If client is setting a function to NOSUPPORT + * or DEFAULT, then we can easily and directly + * accomodate the request. + */ + if (hislevel == SLC_NOSUPPORT) { + slctab[func].current.flag = flag; + slctab[func].current.val = (cc_t)_POSIX_VDISABLE; + flag |= SLC_ACK; + add_slc(func, flag, val); + return; + } + if (hislevel == SLC_DEFAULT) { + /* + * Special case here. If client tells us to use + * the default on a function we don't support, then + * return NOSUPPORT instead of what we may have as a + * default level of DEFAULT. + */ + if (mylevel == SLC_DEFAULT) { + slctab[func].current.flag = SLC_NOSUPPORT; + } else { + slctab[func].current.flag = slctab[func].defset.flag; + } + slctab[func].current.val = slctab[func].defset.val; + add_slc(func, slctab[func].current.flag, + slctab[func].current.val); + return; + } + + /* + * Client wants us to change to a new value or he + * is telling us that he can't change to our value. + * Some of the slc's we support and can change, + * some we do support but can't change, + * and others we don't support at all. + * If we can change it then we have a pointer to + * the place to put the new value, so change it, + * otherwise, continue the negotiation. + */ + if (slctab[func].sptr) { + /* + * We can change this one. + */ + slctab[func].current.val = val; + *(slctab[func].sptr) = val; + slctab[func].current.flag = flag; + flag |= SLC_ACK; + slcchange = 1; + add_slc(func, flag, val); + } else { + /* + * It is not possible for us to support this + * request as he asks. + * + * If our level is DEFAULT, then just ack whatever was + * sent. + * + * If he can't change and we can't change, + * then degenerate to NOSUPPORT. + * + * Otherwise we send our level back to him, (CANTCHANGE + * or NOSUPPORT) and if CANTCHANGE, send + * our value as well. + */ + if (mylevel == SLC_DEFAULT) { + slctab[func].current.flag = flag; + slctab[func].current.val = val; + flag |= SLC_ACK; + } else if (hislevel == SLC_CANTCHANGE && + mylevel == SLC_CANTCHANGE) { + flag &= ~SLC_LEVELBITS; + flag |= SLC_NOSUPPORT; + slctab[func].current.flag = flag; + } else { + flag &= ~SLC_LEVELBITS; + flag |= mylevel; + slctab[func].current.flag = flag; + if (mylevel == SLC_CANTCHANGE) { + slctab[func].current.val = + slctab[func].defset.val; + val = slctab[func].current.val; + } + } + add_slc(func, flag, val); + } + +} /* end of change_slc */ + +#if defined(USE_TERMIO) && (VEOF == VMIN) +cc_t oldeofc = '\004'; +#endif + +/* + * check_slc + * + * Check the special characters in use and notify the client if any have + * changed. Only those characters that are capable of being changed are + * likely to have changed. If a local change occurs, kick the support level + * and flags up to the defaults. + */ + void +check_slc() +{ + register int i; + + for (i = 1; i <= NSLC; i++) { +#if defined(USE_TERMIO) && (VEOF == VMIN) + /* + * In a perfect world this would be a neat little + * function. But in this world, we should not notify + * client of changes to the VEOF char when + * ICANON is off, because it is not representing + * a special character. + */ + if (i == SLC_EOF) { + if (!tty_isediting()) + continue; + else if (slctab[i].sptr) + oldeofc = *(slctab[i].sptr); + } +#endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */ + if (slctab[i].sptr && + (*(slctab[i].sptr) != slctab[i].current.val)) { + slctab[i].current.val = *(slctab[i].sptr); + if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) + slctab[i].current.flag = SLC_NOSUPPORT; + else + slctab[i].current.flag = slctab[i].defset.flag; + add_slc((unsigned char)i, slctab[i].current.flag, + slctab[i].current.val); + } + } +} /* check_slc */ + +/* + * do_opt_slc + * + * Process an slc option buffer. Defer processing of incoming slc's + * until after the terminal state has been processed. Save the first slc + * request that comes along, but discard all others. + * + * ptr points to the beginning of the buffer, len is the length. + */ + void +do_opt_slc(ptr, len) + register unsigned char *ptr; + register int len; +{ + register unsigned char func, flag; + cc_t val; + register unsigned char *end = ptr + len; + + if (terminit()) { /* go ahead */ + while (ptr < end) { + func = *ptr++; + if (ptr >= end) break; + flag = *ptr++; + if (ptr >= end) break; + val = (cc_t)*ptr++; + + process_slc(func, flag, val); + + } + } else { + /* + * save this slc buffer if it is the first, otherwise dump + * it. + */ + if (def_slcbuf == (unsigned char *)0) { + def_slclen = len; + def_slcbuf = (unsigned char *)malloc((unsigned)len); + if (def_slcbuf == (unsigned char *)0) + return; /* too bad */ + memmove(def_slcbuf, ptr, len); + } + } + +} /* end of do_opt_slc */ + +/* + * deferslc + * + * Do slc stuff that was deferred. + */ + void +deferslc() +{ + if (def_slcbuf) { + start_slc(1); + do_opt_slc(def_slcbuf, def_slclen); + (void) end_slc(0); + free(def_slcbuf); + def_slcbuf = (unsigned char *)0; + def_slclen = 0; + } + +} /* end of deferslc */ + +#endif /* LINEMODE */ diff --git a/telnetd.tproj/state.c b/telnetd.tproj/state.c new file mode 100644 index 0000000..60de854 --- /dev/null +++ b/telnetd.tproj/state.c @@ -0,0 +1,1635 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include "telnetd.h" +#if defined(AUTHENTICATION) +#include +#endif + +unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; +unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; +unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; +unsigned char wont[] = { IAC, WONT, '%', 'c', 0 }; +int not42 = 1; + +/* + * Buffer for sub-options, and macros + * for suboptions buffer manipulations + */ +unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer; + +#define SB_CLEAR() subpointer = subbuffer +#define SB_TERM() { subend = subpointer; SB_CLEAR(); } +#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ + *subpointer++ = (c); \ + } +#define SB_GET() ((*subpointer++)&0xff) +#define SB_EOF() (subpointer >= subend) +#define SB_LEN() (subend - subpointer) + +#ifdef ENV_HACK +unsigned char *subsave; +#define SB_SAVE() subsave = subpointer; +#define SB_RESTORE() subpointer = subsave; +#endif + + +/* + * State for recv fsm + */ +#define TS_DATA 0 /* base state */ +#define TS_IAC 1 /* look for double IAC's */ +#define TS_CR 2 /* CR-LF ->'s CR */ +#define TS_SB 3 /* throw away begin's... */ +#define TS_SE 4 /* ...end's (suboption negotiation) */ +#define TS_WILL 5 /* will option negotiation */ +#define TS_WONT 6 /* wont " */ +#define TS_DO 7 /* do " */ +#define TS_DONT 8 /* dont " */ + + void +telrcv() +{ + register int c; + static int state = TS_DATA; +#if defined(CRAY2) && defined(UNICOS5) + char *opfrontp = pfrontp; +#endif + + while (ncc > 0) { + if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) + break; + c = *netip++ & 0377, ncc--; +#ifdef ENCRYPTION + if (decrypt_input) + c = (*decrypt_input)(c); +#endif /* ENCRYPTION */ + switch (state) { + + case TS_CR: + state = TS_DATA; + /* Strip off \n or \0 after a \r */ + if ((c == 0) || (c == '\n')) { + break; + } + /* FALL THROUGH */ + + case TS_DATA: + if (c == IAC) { + state = TS_IAC; + break; + } + /* + * We now map \r\n ==> \r for pragmatic reasons. + * Many client implementations send \r\n when + * the user hits the CarriageReturn key. + * + * We USED to map \r\n ==> \n, since \r\n says + * that we want to be in column 1 of the next + * printable line, and \n is the standard + * unix way of saying that (\r is only good + * if CRMOD is set, which it normally is). + */ + if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { + int nc = *netip; +#ifdef ENCRYPTION + if (decrypt_input) + nc = (*decrypt_input)(nc & 0xff); +#endif /* ENCRYPTION */ +#ifdef LINEMODE + /* + * If we are operating in linemode, + * convert to local end-of-line. + */ + if (linemode && (ncc > 0) && (('\n' == nc) || + ((0 == nc) && tty_iscrnl())) ) { + netip++; ncc--; + c = '\n'; + } else +#endif + { +#ifdef ENCRYPTION + if (decrypt_input) + (void)(*decrypt_input)(-1); +#endif /* ENCRYPTION */ + state = TS_CR; + } + } + *pfrontp++ = c; + break; + + case TS_IAC: +gotiac: switch (c) { + + /* + * Send the process on the pty side an + * interrupt. Do this with a NULL or + * interrupt char; depending on the tty mode. + */ + case IP: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + interrupt(); + break; + + case BREAK: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + sendbrk(); + break; + + /* + * Are You There? + */ + case AYT: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + recv_ayt(); + break; + + /* + * Abort Output + */ + case AO: + { + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + + if (slctab[SLC_AO].sptr && + *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { + *pfrontp++ = + (unsigned char)*slctab[SLC_AO].sptr; + } + + netclear(); /* clear buffer back */ + *nfrontp++ = IAC; + *nfrontp++ = DM; + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + break; + } + + /* + * Erase Character and + * Erase Line + */ + case EC: + case EL: + { + cc_t ch; + + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + ptyflush(); /* half-hearted */ + init_termbuf(); + if (c == EC) + ch = *slctab[SLC_EC].sptr; + else + ch = *slctab[SLC_EL].sptr; + if (ch != (cc_t)(_POSIX_VDISABLE)) + *pfrontp++ = (unsigned char)ch; + break; + } + + /* + * Check for urgent data... + */ + case DM: + DIAG(TD_OPTIONS, + printoption("td: recv IAC", c)); + SYNCHing = stilloob(net); + settimer(gotDM); + break; + + + /* + * Begin option subnegotiation... + */ + case SB: + state = TS_SB; + SB_CLEAR(); + continue; + + case WILL: + state = TS_WILL; + continue; + + case WONT: + state = TS_WONT; + continue; + + case DO: + state = TS_DO; + continue; + + case DONT: + state = TS_DONT; + continue; + case EOR: + if (his_state_is_will(TELOPT_EOR)) + doeof(); + break; + + /* + * Handle RFC 10xx Telnet linemode option additions + * to command stream (EOF, SUSP, ABORT). + */ + case xEOF: + doeof(); + break; + + case SUSP: + sendsusp(); + break; + + case ABORT: + sendbrk(); + break; + + case IAC: + *pfrontp++ = c; + break; + } + state = TS_DATA; + break; + + case TS_SB: + if (c == IAC) { + state = TS_SE; + } else { + SB_ACCUM(c); + } + break; + + case TS_SE: + if (c != SE) { + if (c != IAC) { + /* + * bad form of suboption negotiation. + * handle it in such a way as to avoid + * damage to local state. Parse + * suboption buffer found so far, + * then treat remaining stream as + * another command sequence. + */ + + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(c); + subpointer -= 2; + + SB_TERM(); + suboption(); + state = TS_IAC; + goto gotiac; + } + SB_ACCUM(c); + state = TS_SB; + } else { + /* for DIAGNOSTICS */ + SB_ACCUM(IAC); + SB_ACCUM(SE); + subpointer -= 2; + + SB_TERM(); + suboption(); /* handle sub-option */ + state = TS_DATA; + } + break; + + case TS_WILL: + willoption(c); + state = TS_DATA; + continue; + + case TS_WONT: + wontoption(c); + state = TS_DATA; + continue; + + case TS_DO: + dooption(c); + state = TS_DATA; + continue; + + case TS_DONT: + dontoption(c); + state = TS_DATA; + continue; + + default: + syslog(LOG_ERR, "telnetd: panic state=%d\n", state); + printf("telnetd: panic state=%d\n", state); + exit(1); + } + } +#if defined(CRAY2) && defined(UNICOS5) + if (!linemode) { + char xptyobuf[BUFSIZ+NETSLOP]; + char xbuf2[BUFSIZ]; + register char *cp; + int n = pfrontp - opfrontp, oc; + memmove(xptyobuf, opfrontp, n); + pfrontp = opfrontp; + pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP, + xbuf2, &oc, BUFSIZ); + for (cp = xbuf2; oc > 0; --oc) + if ((*nfrontp++ = *cp++) == IAC) + *nfrontp++ = IAC; + } +#endif /* defined(CRAY2) && defined(UNICOS5) */ +} /* end of telrcv */ + +/* + * The will/wont/do/dont state machines are based on Dave Borman's + * Telnet option processing state machine. + * + * These correspond to the following states: + * my_state = the last negotiated state + * want_state = what I want the state to go to + * want_resp = how many requests I have sent + * All state defaults are negative, and resp defaults to 0. + * + * When initiating a request to change state to new_state: + * + * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { + * do nothing; + * } else { + * want_state = new_state; + * send new_state; + * want_resp++; + * } + * + * When receiving new_state: + * + * if (want_resp) { + * want_resp--; + * if (want_resp && (new_state == my_state)) + * want_resp--; + * } + * if ((want_resp == 0) && (new_state != want_state)) { + * if (ok_to_switch_to new_state) + * want_state = new_state; + * else + * want_resp++; + * send want_state; + * } + * my_state = new_state; + * + * Note that new_state is implied in these functions by the function itself. + * will and do imply positive new_state, wont and dont imply negative. + * + * Finally, there is one catch. If we send a negative response to a + * positive request, my_state will be the positive while want_state will + * remain negative. my_state will revert to negative when the negative + * acknowlegment arrives from the peer. Thus, my_state generally tells + * us not only the last negotiated state, but also tells us what the peer + * wants to be doing as well. It is important to understand this difference + * as we may wish to be processing data streams based on our desired state + * (want_state) or based on what the peer thinks the state is (my_state). + * + * This all works fine because if the peer sends a positive request, the data + * that we receive prior to negative acknowlegment will probably be affected + * by the positive state, and we can process it as such (if we can; if we + * can't then it really doesn't matter). If it is that important, then the + * peer probably should be buffering until this option state negotiation + * is complete. + * + */ + void +send_do(option, init) + int option, init; +{ + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || + his_want_state_is_will(option)) + return; + /* + * Special case for TELOPT_TM: We send a DO, but pretend + * that we sent a DONT, so that we can send more DOs if + * we want to. + */ + if (option == TELOPT_TM) + set_his_want_state_wont(option); + else + set_his_want_state_will(option); + do_dont_resp[option]++; + } + (void) sprintf(nfrontp, (char *)doopt, option); + nfrontp += sizeof (dont) - 2; + + DIAG(TD_OPTIONS, printoption("td: send do", option)); +} + +#ifdef AUTHENTICATION +extern void auth_request(); +#endif +#ifdef LINEMODE +extern void doclientstat(); +#endif +#ifdef ENCRYPTION +extern void encrypt_send_support(); +#endif /* ENCRYPTION */ + + void +willoption(option) + int option; +{ + int changeok = 0; + void (*func)() = 0; + + /* + * process input from peer. + */ + + DIAG(TD_OPTIONS, printoption("td: recv will", option)); + + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_will(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_wont(option)) { + switch (option) { + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(1); + set_termbuf(); + changeok++; + break; + + case TELOPT_ECHO: + /* + * See comments below for more info. + */ + not42 = 0; /* looks like a 4.2 system */ + break; + + case TELOPT_TM: +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + /* + * This telnetd implementation does not really + * support timing marks, it just uses them to + * support the kludge linemode stuff. If we + * receive a will or wont TM in response to our + * do TM request that may have been sent to + * determine kludge linemode support, process + * it, otherwise TM should get a negative + * response back. + */ + /* + * Handle the linemode kludge stuff. + * If we are not currently supporting any + * linemode at all, then we assume that this + * is the client telling us to use kludge + * linemode in response to our query. Set the + * linemode type that is to be supported, note + * that the client wishes to use linemode, and + * eat the will TM as though it never arrived. + */ + if (lmodetype < KLUDGE_LINEMODE) { + lmodetype = KLUDGE_LINEMODE; + clientstat(TELOPT_LINEMODE, WILL, 0); + send_wont(TELOPT_SGA, 1); + } else if (lmodetype == NO_AUTOKLUDGE) { + lmodetype = KLUDGE_OK; + } +#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ + /* + * We never respond to a WILL TM, and + * we leave the state WONT. + */ + return; + + case TELOPT_LFLOW: + /* + * If we are going to support flow control + * option, then don't worry peer that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_DEFAULT; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; + case TELOPT_TTYPE: + case TELOPT_SGA: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_XDISPLOC: + case TELOPT_NEW_ENVIRON: + case TELOPT_OLD_ENVIRON: + changeok++; + break; + +#ifdef LINEMODE + case TELOPT_LINEMODE: +# ifdef KLUDGELINEMODE + /* + * Note client's desire to use linemode. + */ + lmodetype = REAL_LINEMODE; +# endif /* KLUDGELINEMODE */ + func = doclientstat; + changeok++; + break; +#endif /* LINEMODE */ + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + func = auth_request; + changeok++; + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + func = encrypt_send_support; + changeok++; + break; +#endif /* ENCRYPTION */ + + default: + break; + } + if (changeok) { + set_his_want_state_will(option); + send_do(option, 0); + } else { + do_dont_resp[option]++; + send_dont(option, 0); + } + } else { + /* + * Option processing that should happen when + * we receive conformation of a change in + * state that we had requested. + */ + switch (option) { + case TELOPT_ECHO: + not42 = 0; /* looks like a 4.2 system */ + /* + * Egads, he responded "WILL ECHO". Turn + * it off right now! + */ + send_dont(option, 1); + /* + * "WILL ECHO". Kludge upon kludge! + * A 4.2 client is now echoing user input at + * the tty. This is probably undesireable and + * it should be stopped. The client will + * respond WONT TM to the DO TM that we send to + * check for kludge linemode. When the WONT TM + * arrives, linemode will be turned off and a + * change propogated to the pty. This change + * will cause us to process the new pty state + * in localstat(), which will notice that + * linemode is off and send a WILL ECHO + * so that we are properly in character mode and + * all is well. + */ + break; +#ifdef LINEMODE + case TELOPT_LINEMODE: +# ifdef KLUDGELINEMODE + /* + * Note client's desire to use linemode. + */ + lmodetype = REAL_LINEMODE; +# endif /* KLUDGELINEMODE */ + func = doclientstat; + break; +#endif /* LINEMODE */ + +#ifdef AUTHENTICATION + case TELOPT_AUTHENTICATION: + func = auth_request; + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + func = encrypt_send_support; + break; +#endif /* ENCRYPTION */ + case TELOPT_LFLOW: + func = flowstat; + break; + } + } + } + set_his_state_will(option); + if (func) + (*func)(); +} /* end of willoption */ + + void +send_dont(option, init) + int option, init; +{ + if (init) { + if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || + his_want_state_is_wont(option)) + return; + set_his_want_state_wont(option); + do_dont_resp[option]++; + } + (void) sprintf(nfrontp, (char *)dont, option); + nfrontp += sizeof (doopt) - 2; + + DIAG(TD_OPTIONS, printoption("td: send dont", option)); +} + + void +wontoption(option) + int option; +{ + /* + * Process client input. + */ + + DIAG(TD_OPTIONS, printoption("td: recv wont", option)); + + if (do_dont_resp[option]) { + do_dont_resp[option]--; + if (do_dont_resp[option] && his_state_is_wont(option)) + do_dont_resp[option]--; + } + if (do_dont_resp[option] == 0) { + if (his_want_state_is_will(option)) { + /* it is always ok to change to negative state */ + switch (option) { + case TELOPT_ECHO: + not42 = 1; /* doesn't seem to be a 4.2 system */ + break; + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryin(0); + set_termbuf(); + break; + +#ifdef LINEMODE + case TELOPT_LINEMODE: +# ifdef KLUDGELINEMODE + /* + * If real linemode is supported, then client is + * asking to turn linemode off. + */ + if (lmodetype != REAL_LINEMODE) + break; +# endif /* KLUDGELINEMODE */ + clientstat(TELOPT_LINEMODE, WONT, 0); + break; +#endif /* LINEMODE */ + + case TELOPT_TM: + /* + * If we get a WONT TM, and had sent a DO TM, + * don't respond with a DONT TM, just leave it + * as is. Short circut the state machine to + * achive this. + */ + set_his_want_state_wont(TELOPT_TM); + return; + + case TELOPT_LFLOW: + /* + * If we are not going to support flow control + * option, then let peer know that we can't + * change the flow control characters. + */ + slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; + slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; + slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; +#endif + + /* + * For options that we might spin waiting for + * sub-negotiation, if the client turns off the + * option rather than responding to the request, + * we have to treat it here as if we got a response + * to the sub-negotiation, (by updating the timers) + * so that we'll break out of the loop. + */ + case TELOPT_TTYPE: + settimer(ttypesubopt); + break; + + case TELOPT_TSPEED: + settimer(tspeedsubopt); + break; + + case TELOPT_XDISPLOC: + settimer(xdisplocsubopt); + break; + + case TELOPT_OLD_ENVIRON: + settimer(oenvironsubopt); + break; + + case TELOPT_NEW_ENVIRON: + settimer(environsubopt); + break; + + default: + break; + } + set_his_want_state_wont(option); + if (his_state_is_will(option)) + send_dont(option, 0); + } else { + switch (option) { + case TELOPT_TM: +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + if (lmodetype < NO_AUTOKLUDGE) { + lmodetype = NO_LINEMODE; + clientstat(TELOPT_LINEMODE, WONT, 0); + send_will(TELOPT_SGA, 1); + send_will(TELOPT_ECHO, 1); + } +#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + auth_finished(0, AUTH_REJECT); + break; +#endif + default: + break; + } + } + } + set_his_state_wont(option); + +} /* end of wontoption */ + + void +send_will(option, init) + int option, init; +{ + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| + my_want_state_is_will(option)) + return; + set_my_want_state_will(option); + will_wont_resp[option]++; + } + (void) sprintf(nfrontp, (char *)will, option); + nfrontp += sizeof (doopt) - 2; + + DIAG(TD_OPTIONS, printoption("td: send will", option)); +} + +#if !defined(LINEMODE) || !defined(KLUDGELINEMODE) +/* + * When we get a DONT SGA, we will try once to turn it + * back on. If the other side responds DONT SGA, we + * leave it at that. This is so that when we talk to + * clients that understand KLUDGELINEMODE but not LINEMODE, + * we'll keep them in char-at-a-time mode. + */ +int turn_on_sga = 0; +#endif + + void +dooption(option) + int option; +{ + int changeok = 0; + + /* + * Process client input. + */ + + DIAG(TD_OPTIONS, printoption("td: recv do", option)); + + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_will(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { + switch (option) { + case TELOPT_ECHO: +#ifdef LINEMODE +# ifdef KLUDGELINEMODE + if (lmodetype == NO_LINEMODE) +# else + if (his_state_is_wont(TELOPT_LINEMODE)) +# endif +#endif + { + init_termbuf(); + tty_setecho(1); + set_termbuf(); + } + changeok++; + break; + + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(1); + set_termbuf(); + changeok++; + break; + + case TELOPT_SGA: +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + /* + * If kludge linemode is in use, then we must + * process an incoming do SGA for linemode + * purposes. + */ + if (lmodetype == KLUDGE_LINEMODE) { + /* + * Receipt of "do SGA" in kludge + * linemode is the peer asking us to + * turn off linemode. Make note of + * the request. + */ + clientstat(TELOPT_LINEMODE, WONT, 0); + /* + * If linemode did not get turned off + * then don't tell peer that we did. + * Breaking here forces a wont SGA to + * be returned. + */ + if (linemode) + break; + } +#else + turn_on_sga = 0; +#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ + changeok++; + break; + + case TELOPT_STATUS: + changeok++; + break; + + case TELOPT_TM: + /* + * Special case for TM. We send a WILL, but + * pretend we sent a WONT. + */ + send_will(option, 0); + set_my_want_state_wont(option); + set_my_state_wont(option); + return; + + case TELOPT_LOGOUT: + /* + * When we get a LOGOUT option, respond + * with a WILL LOGOUT, make sure that + * it gets written out to the network, + * and then just go away... + */ + set_my_want_state_will(TELOPT_LOGOUT); + send_will(TELOPT_LOGOUT, 0); + set_my_state_will(TELOPT_LOGOUT); + (void)netflush(); + cleanup(0); + /* NOT REACHED */ + break; + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + changeok++; + break; +#endif /* ENCRYPTION */ + case TELOPT_LINEMODE: + case TELOPT_TTYPE: + case TELOPT_NAWS: + case TELOPT_TSPEED: + case TELOPT_LFLOW: + case TELOPT_XDISPLOC: +#ifdef TELOPT_ENVIRON + case TELOPT_NEW_ENVIRON: +#endif + case TELOPT_OLD_ENVIRON: + default: + break; + } + if (changeok) { + set_my_want_state_will(option); + send_will(option, 0); + } else { + will_wont_resp[option]++; + send_wont(option, 0); + } + } + set_my_state_will(option); + +} /* end of dooption */ + + void +send_wont(option, init) + int option, init; +{ + if (init) { + if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || + my_want_state_is_wont(option)) + return; + set_my_want_state_wont(option); + will_wont_resp[option]++; + } + (void) sprintf(nfrontp, (char *)wont, option); + nfrontp += sizeof (wont) - 2; + + DIAG(TD_OPTIONS, printoption("td: send wont", option)); +} + + void +dontoption(option) + int option; +{ + /* + * Process client input. + */ + + + DIAG(TD_OPTIONS, printoption("td: recv dont", option)); + + if (will_wont_resp[option]) { + will_wont_resp[option]--; + if (will_wont_resp[option] && my_state_is_wont(option)) + will_wont_resp[option]--; + } + if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { + switch (option) { + case TELOPT_BINARY: + init_termbuf(); + tty_binaryout(0); + set_termbuf(); + break; + + case TELOPT_ECHO: /* we should stop echoing */ +#ifdef LINEMODE +# ifdef KLUDGELINEMODE + if ((lmodetype != REAL_LINEMODE) && + (lmodetype != KLUDGE_LINEMODE)) +# else + if (his_state_is_wont(TELOPT_LINEMODE)) +# endif +#endif + { + init_termbuf(); + tty_setecho(0); + set_termbuf(); + } + break; + + case TELOPT_SGA: +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + /* + * If kludge linemode is in use, then we + * must process an incoming do SGA for + * linemode purposes. + */ + if ((lmodetype == KLUDGE_LINEMODE) || + (lmodetype == KLUDGE_OK)) { + /* + * The client is asking us to turn + * linemode on. + */ + lmodetype = KLUDGE_LINEMODE; + clientstat(TELOPT_LINEMODE, WILL, 0); + /* + * If we did not turn line mode on, + * then what do we say? Will SGA? + * This violates design of telnet. + * Gross. Very Gross. + */ + } + break; +#else + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + set_my_state_wont(option); + if (turn_on_sga ^= 1) + send_will(option, 1); + return; +#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ + + default: + break; + } + + set_my_want_state_wont(option); + if (my_state_is_will(option)) + send_wont(option, 0); + } + set_my_state_wont(option); + +} /* end of dontoption */ + +#ifdef ENV_HACK +int env_ovar = -1; +int env_ovalue = -1; +#else /* ENV_HACK */ +# define env_ovar OLD_ENV_VAR +# define env_ovalue OLD_ENV_VALUE +#endif /* ENV_HACK */ + +/* + * suboption() + * + * Look at the sub-option buffer, and try to be helpful to the other + * side. + * + * Currently we recognize: + * + * Terminal type is + * Linemode + * Window size + * Terminal speed + */ + void +suboption() +{ + register int subchar; + + DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); + + subchar = SB_GET(); + switch (subchar) { + case TELOPT_TSPEED: { + register int xspeed, rspeed; + + if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ + break; + + settimer(tspeedsubopt); + + if (SB_EOF() || SB_GET() != TELQUAL_IS) + return; + + xspeed = atoi((char *)subpointer); + + while (SB_GET() != ',' && !SB_EOF()); + if (SB_EOF()) + return; + + rspeed = atoi((char *)subpointer); + clientstat(TELOPT_TSPEED, xspeed, rspeed); + + break; + + } /* end of case TELOPT_TSPEED */ + + case TELOPT_TTYPE: { /* Yaaaay! */ + static char terminalname[41]; + + if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ + break; + settimer(ttypesubopt); + + if (SB_EOF() || SB_GET() != TELQUAL_IS) { + return; /* ??? XXX but, this is the most robust */ + } + + terminaltype = terminalname; + + while ((terminaltype < (terminalname + sizeof terminalname-1)) && + !SB_EOF()) { + register int c; + + c = SB_GET(); + if (isupper(c)) { + c = tolower(c); + } + *terminaltype++ = c; /* accumulate name */ + } + *terminaltype = 0; + terminaltype = terminalname; + break; + } /* end of case TELOPT_TTYPE */ + + case TELOPT_NAWS: { + register int xwinsize, ywinsize; + + if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ + break; + + if (SB_EOF()) + return; + xwinsize = SB_GET() << 8; + if (SB_EOF()) + return; + xwinsize |= SB_GET(); + if (SB_EOF()) + return; + ywinsize = SB_GET() << 8; + if (SB_EOF()) + return; + ywinsize |= SB_GET(); + clientstat(TELOPT_NAWS, xwinsize, ywinsize); + + break; + + } /* end of case TELOPT_NAWS */ + +#ifdef LINEMODE + case TELOPT_LINEMODE: { + register int request; + + if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ + break; + /* + * Process linemode suboptions. + */ + if (SB_EOF()) + break; /* garbage was sent */ + request = SB_GET(); /* get will/wont */ + + if (SB_EOF()) + break; /* another garbage check */ + + if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ + /* + * Process suboption buffer of slc's + */ + start_slc(1); + do_opt_slc(subpointer, subend - subpointer); + (void) end_slc(0); + break; + } else if (request == LM_MODE) { + if (SB_EOF()) + return; + useeditmode = SB_GET(); /* get mode flag */ + clientstat(LM_MODE, 0, 0); + break; + } + + if (SB_EOF()) + break; + switch (SB_GET()) { /* what suboption? */ + case LM_FORWARDMASK: + /* + * According to spec, only server can send request for + * forwardmask, and client can only return a positive response. + * So don't worry about it. + */ + + default: + break; + } + break; + } /* end of case TELOPT_LINEMODE */ +#endif + case TELOPT_STATUS: { + int mode; + + if (SB_EOF()) + break; + mode = SB_GET(); + switch (mode) { + case TELQUAL_SEND: + if (my_state_is_will(TELOPT_STATUS)) + send_status(); + break; + + case TELQUAL_IS: + break; + + default: + break; + } + break; + } /* end of case TELOPT_STATUS */ + + case TELOPT_XDISPLOC: { + if (SB_EOF() || SB_GET() != TELQUAL_IS) + return; + settimer(xdisplocsubopt); + subpointer[SB_LEN()] = '\0'; + (void)setenv("DISPLAY", (char *)subpointer, 1); + break; + } /* end of case TELOPT_XDISPLOC */ + +#ifdef TELOPT_NEW_ENVIRON + case TELOPT_NEW_ENVIRON: +#endif + case TELOPT_OLD_ENVIRON: { + register int c; + register char *cp, *varp, *valp; + + if (SB_EOF()) + return; + c = SB_GET(); + if (c == TELQUAL_IS) { + if (subchar == TELOPT_OLD_ENVIRON) + settimer(oenvironsubopt); + else + settimer(environsubopt); + } else if (c != TELQUAL_INFO) { + return; + } + +#ifdef TELOPT_NEW_ENVIRON + if (subchar == TELOPT_NEW_ENVIRON) { + while (!SB_EOF()) { + c = SB_GET(); + if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) + break; + } + } else +#endif + { +#ifdef ENV_HACK + /* + * We only want to do this if we haven't already decided + * whether or not the other side has its VALUE and VAR + * reversed. + */ + if (env_ovar < 0) { + register int last = -1; /* invalid value */ + int empty = 0; + int got_var = 0, got_value = 0, got_uservar = 0; + + /* + * The other side might have its VALUE and VAR values + * reversed. To be interoperable, we need to determine + * which way it is. If the first recognized character + * is a VAR or VALUE, then that will tell us what + * type of client it is. If the fist recognized + * character is a USERVAR, then we continue scanning + * the suboption looking for two consecutive + * VAR or VALUE fields. We should not get two + * consecutive VALUE fields, so finding two + * consecutive VALUE or VAR fields will tell us + * what the client is. + */ + SB_SAVE(); + while (!SB_EOF()) { + c = SB_GET(); + switch(c) { + case OLD_ENV_VAR: + if (last < 0 || last == OLD_ENV_VAR + || (empty && (last == OLD_ENV_VALUE))) + goto env_ovar_ok; + got_var++; + last = OLD_ENV_VAR; + break; + case OLD_ENV_VALUE: + if (last < 0 || last == OLD_ENV_VALUE + || (empty && (last == OLD_ENV_VAR))) + goto env_ovar_wrong; + got_value++; + last = OLD_ENV_VALUE; + break; + case ENV_USERVAR: + /* count strings of USERVAR as one */ + if (last != ENV_USERVAR) + got_uservar++; + if (empty) { + if (last == OLD_ENV_VALUE) + goto env_ovar_ok; + if (last == OLD_ENV_VAR) + goto env_ovar_wrong; + } + last = ENV_USERVAR; + break; + case ENV_ESC: + if (!SB_EOF()) + c = SB_GET(); + /* FALL THROUGH */ + default: + empty = 0; + continue; + } + empty = 1; + } + if (empty) { + if (last == OLD_ENV_VALUE) + goto env_ovar_ok; + if (last == OLD_ENV_VAR) + goto env_ovar_wrong; + } + /* + * Ok, the first thing was a USERVAR, and there + * are not two consecutive VAR or VALUE commands, + * and none of the VAR or VALUE commands are empty. + * If the client has sent us a well-formed option, + * then the number of VALUEs received should always + * be less than or equal to the number of VARs and + * USERVARs received. + * + * If we got exactly as many VALUEs as VARs and + * USERVARs, the client has the same definitions. + * + * If we got exactly as many VARs as VALUEs and + * USERVARS, the client has reversed definitions. + */ + if (got_uservar + got_var == got_value) { + env_ovar_ok: + env_ovar = OLD_ENV_VAR; + env_ovalue = OLD_ENV_VALUE; + } else if (got_uservar + got_value == got_var) { + env_ovar_wrong: + env_ovar = OLD_ENV_VALUE; + env_ovalue = OLD_ENV_VAR; + DIAG(TD_OPTIONS, {sprintf(nfrontp, + "ENVIRON VALUE and VAR are reversed!\r\n"); + nfrontp += strlen(nfrontp);}); + + } + } + SB_RESTORE(); +#endif + + while (!SB_EOF()) { + c = SB_GET(); + if ((c == env_ovar) || (c == ENV_USERVAR)) + break; + } + } + + if (SB_EOF()) + return; + + cp = varp = (char *)subpointer; + valp = 0; + + while (!SB_EOF()) { + c = SB_GET(); + if (subchar == TELOPT_OLD_ENVIRON) { + if (c == env_ovar) + c = NEW_ENV_VAR; + else if (c == env_ovalue) + c = NEW_ENV_VALUE; + } + switch (c) { + + case NEW_ENV_VALUE: + *cp = '\0'; + cp = valp = (char *)subpointer; + break; + + case NEW_ENV_VAR: + case ENV_USERVAR: + *cp = '\0'; + if (valp) + (void)setenv(varp, valp, 1); + else + unsetenv(varp); + cp = varp = (char *)subpointer; + valp = 0; + break; + + case ENV_ESC: + if (SB_EOF()) + break; + c = SB_GET(); + /* FALL THROUGH */ + default: + *cp++ = c; + break; + } + } + *cp = '\0'; + if (valp) + (void)setenv(varp, valp, 1); + else + unsetenv(varp); + break; + } /* end of case TELOPT_NEW_ENVIRON */ +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + if (SB_EOF()) + break; + switch(SB_GET()) { + case TELQUAL_SEND: + case TELQUAL_REPLY: + /* + * These are sent by us and cannot be sent by + * the client. + */ + break; + case TELQUAL_IS: + auth_is(subpointer, SB_LEN()); + break; + case TELQUAL_NAME: + auth_name(subpointer, SB_LEN()); + break; + } + break; +#endif +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + if (SB_EOF()) + break; + switch(SB_GET()) { + case ENCRYPT_SUPPORT: + encrypt_support(subpointer, SB_LEN()); + break; + case ENCRYPT_IS: + encrypt_is(subpointer, SB_LEN()); + break; + case ENCRYPT_REPLY: + encrypt_reply(subpointer, SB_LEN()); + break; + case ENCRYPT_START: + encrypt_start(subpointer, SB_LEN()); + break; + case ENCRYPT_END: + encrypt_end(); + break; + case ENCRYPT_REQSTART: + encrypt_request_start(subpointer, SB_LEN()); + break; + case ENCRYPT_REQEND: + /* + * We can always send an REQEND so that we cannot + * get stuck encrypting. We should only get this + * if we have been able to get in the correct mode + * anyhow. + */ + encrypt_request_end(); + break; + case ENCRYPT_ENC_KEYID: + encrypt_enc_keyid(subpointer, SB_LEN()); + break; + case ENCRYPT_DEC_KEYID: + encrypt_dec_keyid(subpointer, SB_LEN()); + break; + default: + break; + } + break; +#endif /* ENCRYPTION */ + + default: + break; + } /* end of switch */ + +} /* end of suboption */ + + void +doclientstat() +{ + clientstat(TELOPT_LINEMODE, WILL, 0); +} + +#define ADD(c) *ncp++ = c +#define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } + void +send_status() +{ + unsigned char statusbuf[256]; + register unsigned char *ncp; + register unsigned char i; + + ncp = statusbuf; + + netflush(); /* get rid of anything waiting to go out */ + + ADD(IAC); + ADD(SB); + ADD(TELOPT_STATUS); + ADD(TELQUAL_IS); + + /* + * We check the want_state rather than the current state, + * because if we received a DO/WILL for an option that we + * don't support, and the other side didn't send a DONT/WONT + * in response to our WONT/DONT, then the "state" will be + * WILL/DO, and the "want_state" will be WONT/DONT. We + * need to go by the latter. + */ + for (i = 0; i < (unsigned char)NTELOPTS; i++) { + if (my_want_state_is_will(i)) { + ADD(WILL); + ADD_DATA(i); + } + if (his_want_state_is_will(i)) { + ADD(DO); + ADD_DATA(i); + } + } + + if (his_want_state_is_will(TELOPT_LFLOW)) { + ADD(SB); + ADD(TELOPT_LFLOW); + if (flowmode) { + ADD(LFLOW_ON); + } else { + ADD(LFLOW_OFF); + } + ADD(SE); + + if (restartany >= 0) { + ADD(SB); + ADD(TELOPT_LFLOW); + if (restartany) { + ADD(LFLOW_RESTART_ANY); + } else { + ADD(LFLOW_RESTART_XON); + } + ADD(SE); + } + } + +#ifdef LINEMODE + if (his_want_state_is_will(TELOPT_LINEMODE)) { + unsigned char *cp, *cpe; + int len; + + ADD(SB); + ADD(TELOPT_LINEMODE); + ADD(LM_MODE); + ADD_DATA(editmode); + ADD(SE); + + ADD(SB); + ADD(TELOPT_LINEMODE); + ADD(LM_SLC); + start_slc(0); + send_slc(); + len = end_slc(&cp); + for (cpe = cp + len; cp < cpe; cp++) + ADD_DATA(*cp); + ADD(SE); + } +#endif /* LINEMODE */ + + ADD(IAC); + ADD(SE); + + writenet(statusbuf, ncp - statusbuf); + netflush(); /* Send it on its way */ + + DIAG(TD_OPTIONS, + {printsub('>', statusbuf, ncp - statusbuf); netflush();}); +} diff --git a/telnetd.tproj/sys_term.c b/telnetd.tproj/sys_term.c new file mode 100644 index 0000000..61d116e --- /dev/null +++ b/telnetd.tproj/sys_term.c @@ -0,0 +1,2306 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)sys_term.c 8.4 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include "telnetd.h" +#include "pathnames.h" + +#if defined(AUTHENTICATION) +#include +#endif + +#if defined(CRAY) || defined(__hpux) +# define PARENT_DOES_UTMP +#endif + +#ifdef NEWINIT +#include +int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */ +#else /* NEWINIT*/ +# ifdef UTMPX +# include +struct utmpx wtmp; +# else +# include +struct utmp wtmp; +# endif /* UTMPX */ + +int utmp_len = sizeof(wtmp.ut_host); +# ifndef PARENT_DOES_UTMP +char wtmpf[] = "/usr/adm/wtmp"; +char utmpf[] = "/var/run/utmp"; +# else /* PARENT_DOES_UTMP */ +char wtmpf[] = "/etc/wtmp"; +# endif /* PARENT_DOES_UTMP */ + +# ifdef CRAY +#include +#include +# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') +# define UNICOS7x +# endif + +# ifdef UNICOS7x +#include +#include +extern int secflag; +extern struct sysv sysv; +# endif /* UNICOS7x */ +# endif /* CRAY */ +#endif /* NEWINIT */ + +#ifdef STREAMSPTY +#include +#include +#endif + +#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) +#define SCMPN(a, b) strncmp(a, b, sizeof(a)) + +#ifdef STREAMS +#include +#endif +#ifdef __hpux +#include +#include +#endif +#include +#ifdef t_erase +#undef t_erase +#undef t_kill +#undef t_intrc +#undef t_quitc +#undef t_startc +#undef t_stopc +#undef t_eofc +#undef t_brkc +#undef t_suspc +#undef t_dsuspc +#undef t_rprntc +#undef t_flushc +#undef t_werasc +#undef t_lnextc +#endif + +#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) +# define EXTPROC 0400 +#endif + +#ifndef USE_TERMIO +struct termbuf { + struct sgttyb sg; + struct tchars tc; + struct ltchars ltc; + int state; + int lflags; +} termbuf, termbuf2; +# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) +# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) +# define cfgetospeed(tp) (tp)->sg.sg_ospeed +# define cfgetispeed(tp) (tp)->sg.sg_ispeed +#else /* USE_TERMIO */ +# ifdef SYSV_TERMIO +# define termios termio +# endif +# ifndef TCSANOW +# ifdef TCSETS +# define TCSANOW TCSETS +# define TCSADRAIN TCSETSW +# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) +# else +# ifdef TCSETA +# define TCSANOW TCSETA +# define TCSADRAIN TCSETAW +# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) +# else +# define TCSANOW TIOCSETA +# define TCSADRAIN TIOCSETAW +# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) +# endif +# endif +# define tcsetattr(f, a, t) ioctl(f, a, t) +# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ + (tp)->c_cflag |= (val) +# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) +# ifdef CIBAUD +# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ + (tp)->c_cflag |= ((val)<c_cflag & CIBAUD)>>IBSHIFT) +# else +# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ + (tp)->c_cflag |= (val) +# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) +# endif +# endif /* TCSANOW */ +struct termios termbuf, termbuf2; /* pty control structure */ +# ifdef STREAMSPTY +int ttyfd = -1; +# endif +#endif /* USE_TERMIO */ + +/* + * init_termbuf() + * copy_termbuf(cp) + * set_termbuf() + * + * These three routines are used to get and set the "termbuf" structure + * to and from the kernel. init_termbuf() gets the current settings. + * copy_termbuf() hands in a new "termbuf" to write to the kernel, and + * set_termbuf() writes the structure into the kernel. + */ + + void +init_termbuf() +{ +#ifndef USE_TERMIO + (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); + (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); + (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); +# ifdef TIOCGSTATE + (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); +# endif +#else +# ifdef STREAMSPTY + (void) tcgetattr(ttyfd, &termbuf); +# else + (void) tcgetattr(pty, &termbuf); +# endif +#endif + termbuf2 = termbuf; +} + +#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) + void +copy_termbuf(cp, len) + char *cp; + int len; +{ + if (len > sizeof(termbuf)) + len = sizeof(termbuf); + memmove((char *)&termbuf, cp, len); + termbuf2 = termbuf; +} +#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ + + void +set_termbuf() +{ + /* + * Only make the necessary changes. + */ +#ifndef USE_TERMIO + if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, + sizeof(termbuf.sg))) + (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); + if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, + sizeof(termbuf.tc))) + (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); + if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, + sizeof(termbuf.ltc))) + (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); + if (termbuf.lflags != termbuf2.lflags) + (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); +#else /* USE_TERMIO */ + if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) +# ifdef STREAMSPTY + (void) tcsetattr(ttyfd, TCSANOW, &termbuf); +# else + (void) tcsetattr(pty, TCSANOW, &termbuf); +# endif +# if defined(CRAY2) && defined(UNICOS5) + needtermstat = 1; +# endif +#endif /* USE_TERMIO */ +} + + +/* + * spcset(func, valp, valpp) + * + * This function takes various special characters (func), and + * sets *valp to the current value of that character, and + * *valpp to point to where in the "termbuf" structure that + * value is kept. + * + * It returns the SLC_ level of support for this function. + */ + +#ifndef USE_TERMIO + int +spcset(func, valp, valpp) + int func; + cc_t *valp; + cc_t **valpp; +{ + switch(func) { + case SLC_EOF: + *valp = termbuf.tc.t_eofc; + *valpp = (cc_t *)&termbuf.tc.t_eofc; + return(SLC_VARIABLE); + case SLC_EC: + *valp = termbuf.sg.sg_erase; + *valpp = (cc_t *)&termbuf.sg.sg_erase; + return(SLC_VARIABLE); + case SLC_EL: + *valp = termbuf.sg.sg_kill; + *valpp = (cc_t *)&termbuf.sg.sg_kill; + return(SLC_VARIABLE); + case SLC_IP: + *valp = termbuf.tc.t_intrc; + *valpp = (cc_t *)&termbuf.tc.t_intrc; + return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_ABORT: + *valp = termbuf.tc.t_quitc; + *valpp = (cc_t *)&termbuf.tc.t_quitc; + return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_XON: + *valp = termbuf.tc.t_startc; + *valpp = (cc_t *)&termbuf.tc.t_startc; + return(SLC_VARIABLE); + case SLC_XOFF: + *valp = termbuf.tc.t_stopc; + *valpp = (cc_t *)&termbuf.tc.t_stopc; + return(SLC_VARIABLE); + case SLC_AO: + *valp = termbuf.ltc.t_flushc; + *valpp = (cc_t *)&termbuf.ltc.t_flushc; + return(SLC_VARIABLE); + case SLC_SUSP: + *valp = termbuf.ltc.t_suspc; + *valpp = (cc_t *)&termbuf.ltc.t_suspc; + return(SLC_VARIABLE); + case SLC_EW: + *valp = termbuf.ltc.t_werasc; + *valpp = (cc_t *)&termbuf.ltc.t_werasc; + return(SLC_VARIABLE); + case SLC_RP: + *valp = termbuf.ltc.t_rprntc; + *valpp = (cc_t *)&termbuf.ltc.t_rprntc; + return(SLC_VARIABLE); + case SLC_LNEXT: + *valp = termbuf.ltc.t_lnextc; + *valpp = (cc_t *)&termbuf.ltc.t_lnextc; + return(SLC_VARIABLE); + case SLC_FORW1: + *valp = termbuf.tc.t_brkc; + *valpp = (cc_t *)&termbuf.ltc.t_lnextc; + return(SLC_VARIABLE); + case SLC_BRK: + case SLC_SYNCH: + case SLC_AYT: + case SLC_EOR: + *valp = (cc_t)0; + *valpp = (cc_t *)0; + return(SLC_DEFAULT); + default: + *valp = (cc_t)0; + *valpp = (cc_t *)0; + return(SLC_NOSUPPORT); + } +} + +#else /* USE_TERMIO */ + + int +spcset(func, valp, valpp) + int func; + cc_t *valp; + cc_t **valpp; +{ + +#define setval(a, b) *valp = termbuf.c_cc[a]; \ + *valpp = &termbuf.c_cc[a]; \ + return(b); +#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); + + switch(func) { + case SLC_EOF: + setval(VEOF, SLC_VARIABLE); + case SLC_EC: + setval(VERASE, SLC_VARIABLE); + case SLC_EL: + setval(VKILL, SLC_VARIABLE); + case SLC_IP: + setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_ABORT: + setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); + case SLC_XON: +#ifdef VSTART + setval(VSTART, SLC_VARIABLE); +#else + defval(0x13); +#endif + case SLC_XOFF: +#ifdef VSTOP + setval(VSTOP, SLC_VARIABLE); +#else + defval(0x11); +#endif + case SLC_EW: +#ifdef VWERASE + setval(VWERASE, SLC_VARIABLE); +#else + defval(0); +#endif + case SLC_RP: +#ifdef VREPRINT + setval(VREPRINT, SLC_VARIABLE); +#else + defval(0); +#endif + case SLC_LNEXT: +#ifdef VLNEXT + setval(VLNEXT, SLC_VARIABLE); +#else + defval(0); +#endif + case SLC_AO: +#if !defined(VDISCARD) && defined(VFLUSHO) +# define VDISCARD VFLUSHO +#endif +#ifdef VDISCARD + setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); +#else + defval(0); +#endif + case SLC_SUSP: +#ifdef VSUSP + setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); +#else + defval(0); +#endif +#ifdef VEOL + case SLC_FORW1: + setval(VEOL, SLC_VARIABLE); +#endif +#ifdef VEOL2 + case SLC_FORW2: + setval(VEOL2, SLC_VARIABLE); +#endif + case SLC_AYT: +#ifdef VSTATUS + setval(VSTATUS, SLC_VARIABLE); +#else + defval(0); +#endif + + case SLC_BRK: + case SLC_SYNCH: + case SLC_EOR: + defval(0); + + default: + *valp = 0; + *valpp = 0; + return(SLC_NOSUPPORT); + } +} +#endif /* USE_TERMIO */ + +#ifdef CRAY +/* + * getnpty() + * + * Return the number of pty's configured into the system. + */ + int +getnpty() +{ +#ifdef _SC_CRAY_NPTY + int numptys; + + if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) + return numptys; + else +#endif /* _SC_CRAY_NPTY */ + return 128; +} +#endif /* CRAY */ + +#ifndef convex +/* + * getpty() + * + * Allocate a pty. As a side effect, the external character + * array "line" contains the name of the slave side. + * + * Returns the file descriptor of the opened pty. + */ +#ifndef __APPLE__ +#ifndef __GNUC__ +char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +#else +static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +char *line = Xline; +#endif +#ifdef CRAY +char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; +#endif /* CRAY */ +#endif /* !NeXT */ + + int +getpty(ptynum) +int *ptynum; +{ + register int p; +#ifdef STREAMSPTY + int t; + char *ptsname(); + + p = open("/dev/ptmx", 2); + if (p > 0) { + grantpt(p); + unlockpt(p); + strcpy(line, ptsname(p)); + return(p); + } + +#else /* ! STREAMSPTY */ +#ifndef CRAY + register char *cp, *p1, *p2; + register int i; +#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 + int dummy; +#endif + +#ifndef __hpux + (void) sprintf(line, "/dev/ptyXX"); + p1 = &line[8]; + p2 = &line[9]; +#else + (void) sprintf(line, "/dev/ptym/ptyXX"); + p1 = &line[13]; + p2 = &line[14]; +#endif + + for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { + struct stat stb; + + *p1 = *cp; + *p2 = '0'; + /* + * This stat() check is just to keep us from + * looping through all 256 combinations if there + * aren't that many ptys available. + */ + if (stat(line, &stb) < 0) + break; + for (i = 0; i < 16; i++) { + *p2 = "0123456789abcdef"[i]; + p = open(line, 2); + if (p > 0) { +#ifndef __hpux + line[5] = 't'; +#else + for (p1 = &line[8]; *p1; p1++) + *p1 = *(p1+1); + line[9] = 't'; +#endif + chown(line, 0, 0); + chmod(line, 0600); +#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 + if (ioctl(p, TIOCGPGRP, &dummy) == 0 + || errno != EIO) { + chmod(line, 0666); + close(p); + line[5] = 'p'; + } else +#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ + return(p); + } + } + } +#else /* CRAY */ + extern lowpty, highpty; + struct stat sb; + + for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { + (void) sprintf(myline, "/dev/pty/%03d", *ptynum); + p = open(myline, 2); + if (p < 0) + continue; + (void) sprintf(line, "/dev/ttyp%03d", *ptynum); + /* + * Here are some shenanigans to make sure that there + * are no listeners lurking on the line. + */ + if(stat(line, &sb) < 0) { + (void) close(p); + continue; + } + if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { + chown(line, 0, 0); + chmod(line, 0600); + (void)close(p); + p = open(myline, 2); + if (p < 0) + continue; + } + /* + * Now it should be safe...check for accessability. + */ + if (access(line, 6) == 0) + return(p); + else { + /* no tty side to pty so skip it */ + (void) close(p); + } + } +#endif /* CRAY */ +#endif /* STREAMSPTY */ + return(-1); +} +#endif /* convex */ + +#ifdef LINEMODE +/* + * tty_flowmode() Find out if flow control is enabled or disabled. + * tty_linemode() Find out if linemode (external processing) is enabled. + * tty_setlinemod(on) Turn on/off linemode. + * tty_isecho() Find out if echoing is turned on. + * tty_setecho(on) Enable/disable character echoing. + * tty_israw() Find out if terminal is in RAW mode. + * tty_binaryin(on) Turn on/off BINARY on input. + * tty_binaryout(on) Turn on/off BINARY on output. + * tty_isediting() Find out if line editing is enabled. + * tty_istrapsig() Find out if signal trapping is enabled. + * tty_setedit(on) Turn on/off line editing. + * tty_setsig(on) Turn on/off signal trapping. + * tty_issofttab() Find out if tab expansion is enabled. + * tty_setsofttab(on) Turn on/off soft tab expansion. + * tty_islitecho() Find out if typed control chars are echoed literally + * tty_setlitecho() Turn on/off literal echo of control chars + * tty_tspeed(val) Set transmit speed to val. + * tty_rspeed(val) Set receive speed to val. + */ + +#ifdef convex +static int linestate; +#endif + + int +tty_linemode() +{ +#ifndef convex +#ifndef USE_TERMIO + return(termbuf.state & TS_EXTPROC); +#else + return(termbuf.c_lflag & EXTPROC); +#endif +#else + return(linestate); +#endif +} + + void +tty_setlinemode(on) + int on; +{ +#ifdef TIOCEXT +# ifndef convex + set_termbuf(); +# else + linestate = on; +# endif + (void) ioctl(pty, TIOCEXT, (char *)&on); +# ifndef convex + init_termbuf(); +# endif +#else /* !TIOCEXT */ +# ifdef EXTPROC + if (on) + termbuf.c_lflag |= EXTPROC; + else + termbuf.c_lflag &= ~EXTPROC; +# endif +#endif /* TIOCEXT */ +} +#endif /* LINEMODE */ + + int +tty_isecho() +{ +#ifndef USE_TERMIO + return (termbuf.sg.sg_flags & ECHO); +#else + return (termbuf.c_lflag & ECHO); +#endif +} + + int +tty_flowmode() +{ +#ifndef USE_TERMIO + return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); +#else + return((termbuf.c_iflag & IXON) ? 1 : 0); +#endif +} + + int +tty_restartany() +{ +#ifndef USE_TERMIO +# ifdef DECCTQ + return((termbuf.lflags & DECCTQ) ? 0 : 1); +# else + return(-1); +# endif +#else + return((termbuf.c_iflag & IXANY) ? 1 : 0); +#endif +} + + void +tty_setecho(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + termbuf.sg.sg_flags |= ECHO|CRMOD; + else + termbuf.sg.sg_flags &= ~(ECHO|CRMOD); +#else + if (on) + termbuf.c_lflag |= ECHO; + else + termbuf.c_lflag &= ~ECHO; +#endif +} + + int +tty_israw() +{ +#ifndef USE_TERMIO + return(termbuf.sg.sg_flags & RAW); +#else + return(!(termbuf.c_lflag & ICANON)); +#endif +} + +#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) + int +tty_setraw(on) +{ +# ifndef USE_TERMIO + if (on) + termbuf.sg.sg_flags |= RAW; + else + termbuf.sg.sg_flags &= ~RAW; +# else + if (on) + termbuf.c_lflag &= ~ICANON; + else + termbuf.c_lflag |= ICANON; +# endif +} +#endif + + void +tty_binaryin(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + termbuf.lflags |= LPASS8; + else + termbuf.lflags &= ~LPASS8; +#else + if (on) { + termbuf.c_iflag &= ~ISTRIP; + } else { + termbuf.c_iflag |= ISTRIP; + } +#endif +} + + void +tty_binaryout(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + termbuf.lflags |= LLITOUT; + else + termbuf.lflags &= ~LLITOUT; +#else + if (on) { + termbuf.c_cflag &= ~(CSIZE|PARENB); + termbuf.c_cflag |= CS8; + termbuf.c_oflag &= ~OPOST; + } else { + termbuf.c_cflag &= ~CSIZE; + termbuf.c_cflag |= CS7|PARENB; + termbuf.c_oflag |= OPOST; + } +#endif +} + + int +tty_isbinaryin() +{ +#ifndef USE_TERMIO + return(termbuf.lflags & LPASS8); +#else + return(!(termbuf.c_iflag & ISTRIP)); +#endif +} + + int +tty_isbinaryout() +{ +#ifndef USE_TERMIO + return(termbuf.lflags & LLITOUT); +#else + return(!(termbuf.c_oflag&OPOST)); +#endif +} + +#ifdef LINEMODE + int +tty_isediting() +{ +#ifndef USE_TERMIO + return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); +#else + return(termbuf.c_lflag & ICANON); +#endif +} + + int +tty_istrapsig() +{ +#ifndef USE_TERMIO + return(!(termbuf.sg.sg_flags&RAW)); +#else + return(termbuf.c_lflag & ISIG); +#endif +} + + void +tty_setedit(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + termbuf.sg.sg_flags &= ~CBREAK; + else + termbuf.sg.sg_flags |= CBREAK; +#else + if (on) + termbuf.c_lflag |= ICANON; + else + termbuf.c_lflag &= ~ICANON; +#endif +} + + void +tty_setsig(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + ; +#else + if (on) + termbuf.c_lflag |= ISIG; + else + termbuf.c_lflag &= ~ISIG; +#endif +} +#endif /* LINEMODE */ + + int +tty_issofttab() +{ +#ifndef USE_TERMIO + return (termbuf.sg.sg_flags & XTABS); +#else +# ifdef OXTABS + return (termbuf.c_oflag & OXTABS); +# endif +# ifdef TABDLY + return ((termbuf.c_oflag & TABDLY) == TAB3); +# endif +#endif +} + + void +tty_setsofttab(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + termbuf.sg.sg_flags |= XTABS; + else + termbuf.sg.sg_flags &= ~XTABS; +#else + if (on) { +# ifdef OXTABS + termbuf.c_oflag |= OXTABS; +# endif +# ifdef TABDLY + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB3; +# endif + } else { +# ifdef OXTABS + termbuf.c_oflag &= ~OXTABS; +# endif +# ifdef TABDLY + termbuf.c_oflag &= ~TABDLY; + termbuf.c_oflag |= TAB0; +# endif + } +#endif +} + + int +tty_islitecho() +{ +#ifndef USE_TERMIO + return (!(termbuf.lflags & LCTLECH)); +#else +# ifdef ECHOCTL + return (!(termbuf.c_lflag & ECHOCTL)); +# endif +# ifdef TCTLECH + return (!(termbuf.c_lflag & TCTLECH)); +# endif +# if !defined(ECHOCTL) && !defined(TCTLECH) + return (0); /* assumes ctl chars are echoed '^x' */ +# endif +#endif +} + + void +tty_setlitecho(on) + int on; +{ +#ifndef USE_TERMIO + if (on) + termbuf.lflags &= ~LCTLECH; + else + termbuf.lflags |= LCTLECH; +#else +# ifdef ECHOCTL + if (on) + termbuf.c_lflag &= ~ECHOCTL; + else + termbuf.c_lflag |= ECHOCTL; +# endif +# ifdef TCTLECH + if (on) + termbuf.c_lflag &= ~TCTLECH; + else + termbuf.c_lflag |= TCTLECH; +# endif +#endif +} + + int +tty_iscrnl() +{ +#ifndef USE_TERMIO + return (termbuf.sg.sg_flags & CRMOD); +#else + return (termbuf.c_iflag & ICRNL); +#endif +} + +/* + * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). + */ +#if B4800 != 4800 +#define DECODE_BAUD +#endif + +#ifdef DECODE_BAUD + +/* + * A table of available terminal speeds + */ +struct termspeeds { + int speed; + int value; +} termspeeds[] = { + { 0, B0 }, { 50, B50 }, { 75, B75 }, + { 110, B110 }, { 134, B134 }, { 150, B150 }, + { 200, B200 }, { 300, B300 }, { 600, B600 }, + { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, + { 4800, B4800 }, +#ifdef B7200 + { 7200, B7200 }, +#endif + { 9600, B9600 }, +#ifdef B14400 + { 14400, B14400 }, +#endif +#ifdef B19200 + { 19200, B19200 }, +#endif +#ifdef B28800 + { 28800, B28800 }, +#endif +#ifdef B38400 + { 38400, B38400 }, +#endif +#ifdef B57600 + { 57600, B57600 }, +#endif +#ifdef B115200 + { 115200, B115200 }, +#endif +#ifdef B230400 + { 230400, B230400 }, +#endif + { -1, 0 } +}; +#endif /* DECODE_BUAD */ + + void +tty_tspeed(val) + int val; +{ +#ifdef DECODE_BAUD + register struct termspeeds *tp; + + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetospeed(&termbuf, tp->value); +#else /* DECODE_BUAD */ + cfsetospeed(&termbuf, val); +#endif /* DECODE_BUAD */ +} + + void +tty_rspeed(val) + int val; +{ +#ifdef DECODE_BAUD + register struct termspeeds *tp; + + for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) + ; + if (tp->speed == -1) /* back up to last valid value */ + --tp; + cfsetispeed(&termbuf, tp->value); +#else /* DECODE_BAUD */ + cfsetispeed(&termbuf, val); +#endif /* DECODE_BAUD */ +} + +#if defined(CRAY2) && defined(UNICOS5) + int +tty_isnewmap() +{ + return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && + !(termbuf.c_oflag & ONLRET)); +} +#endif + +#ifdef PARENT_DOES_UTMP +# ifndef NEWINIT +extern struct utmp wtmp; +extern char wtmpf[]; +# else /* NEWINIT */ +int gotalarm; + + /* ARGSUSED */ + void +nologinproc(sig) + int sig; +{ + gotalarm++; +} +# endif /* NEWINIT */ +#endif /* PARENT_DOES_UTMP */ + +#ifndef NEWINIT +# ifdef PARENT_DOES_UTMP +extern void utmp_sig_init P((void)); +extern void utmp_sig_reset P((void)); +extern void utmp_sig_wait P((void)); +extern void utmp_sig_notify P((int)); +# endif /* PARENT_DOES_UTMP */ +#endif + +/* + * getptyslave() + * + * Open the slave side of the pty, and do any initialization + * that is necessary. The return value is a file descriptor + * for the slave side. + */ + int +getptyslave() +{ + register int t = -1; + +#if !defined(CRAY) || !defined(NEWINIT) +# ifdef LINEMODE + int waslm; +# endif +# ifdef TIOCGWINSZ + struct winsize ws; + extern int def_row, def_col; +# endif + extern int def_tspeed, def_rspeed; + /* + * Opening the slave side may cause initilization of the + * kernel tty structure. We need remember the state of + * if linemode was turned on + * terminal window size + * terminal speed + * so that we can re-set them if we need to. + */ +# ifdef LINEMODE + waslm = tty_linemode(); +# endif + + + /* + * Make sure that we don't have a controlling tty, and + * that we are the session (process group) leader. + */ +# ifdef TIOCNOTTY + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + (void) ioctl(t, TIOCNOTTY, (char *)0); + (void) close(t); + } +# endif + + +# ifdef PARENT_DOES_UTMP + /* + * Wait for our parent to get the utmp stuff to get done. + */ + utmp_sig_wait(); +# endif + + t = cleanopen(line); + if (t < 0) + fatalperror(net, line); + +#ifdef STREAMSPTY +#ifdef USE_TERMIO + ttyfd = t; +#endif + if (ioctl(t, I_PUSH, "ptem") < 0) + fatal(net, "I_PUSH ptem"); + if (ioctl(t, I_PUSH, "ldterm") < 0) + fatal(net, "I_PUSH ldterm"); + if (ioctl(t, I_PUSH, "ttcompat") < 0) + fatal(net, "I_PUSH ttcompat"); + if (ioctl(pty, I_PUSH, "pckt") < 0) + fatal(net, "I_PUSH pckt"); +#endif + + /* + * set up the tty modes as we like them to be. + */ + init_termbuf(); +# ifdef TIOCGWINSZ + if (def_row || def_col) { + memset((char *)&ws, 0, sizeof(ws)); + ws.ws_col = def_col; + ws.ws_row = def_row; + (void)ioctl(t, TIOCSWINSZ, (char *)&ws); + } +# endif + + /* + * Settings for sgtty based systems + */ +# ifndef USE_TERMIO + termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; +# endif /* USE_TERMIO */ + + /* + * Settings for UNICOS (and HPUX) + */ +# if defined(CRAY) || defined(__hpux) + termbuf.c_oflag = OPOST|ONLCR|TAB3; + termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; + termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; + termbuf.c_cflag = EXTB|HUPCL|CS8; +# endif + + /* + * Settings for all other termios/termio based + * systems, other than 4.4BSD. In 4.4BSD the + * kernel does the initial terminal setup. + */ +# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) +# ifndef OXTABS +# define OXTABS 0 +# endif + termbuf.c_lflag |= ECHO; + termbuf.c_oflag |= ONLCR|OXTABS; + termbuf.c_iflag |= ICRNL; + termbuf.c_iflag &= ~IXOFF; +# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ + tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); + tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); +# ifdef LINEMODE + if (waslm) + tty_setlinemode(1); +# endif /* LINEMODE */ + + /* + * Set the tty modes, and make this our controlling tty. + */ + set_termbuf(); + if (login_tty(t) == -1) + fatalperror(net, "login_tty"); +#endif /* !defined(CRAY) || !defined(NEWINIT) */ + if (net > 2) + (void) close(net); +#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) + /* + * Leave the pty open so that we can write out the rlogin + * protocol for /bin/login, if the authentication works. + */ +#else + if (pty > 2) { + (void) close(pty); + pty = -1; + } +#endif +} + +#if !defined(CRAY) || !defined(NEWINIT) +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif +/* + * Open the specified slave side of the pty, + * making sure that we have a clean tty. + */ + int +cleanopen(line) + char *line; +{ + register int t; +#ifdef UNICOS7x + struct secstat secbuf; +#endif /* UNICOS7x */ + +#ifndef STREAMSPTY + /* + * Make sure that other people can't open the + * slave side of the connection. + */ + (void) chown(line, 0, 0); + (void) chmod(line, 0600); +#endif + +# if !defined(CRAY) && (BSD > 43) + (void) revoke(line); +# endif +#ifdef UNICOS7x + if (secflag) { + if (secstat(line, &secbuf) < 0) + return(-1); + if (setulvl(secbuf.st_slevel) < 0) + return(-1); + if (setucmp(secbuf.st_compart) < 0) + return(-1); + } +#endif /* UNICOS7x */ + + t = open(line, O_RDWR|O_NOCTTY); + +#ifdef UNICOS7x + if (secflag) { + if (setulvl(sysv.sy_minlvl) < 0) + return(-1); + if (setucmp(0) < 0) + return(-1); + } +#endif /* UNICOS7x */ + + if (t < 0) + return(-1); + + /* + * Hangup anybody else using this ttyp, then reopen it for + * ourselves. + */ +# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) + (void) signal(SIGHUP, SIG_IGN); + vhangup(); + (void) signal(SIGHUP, SIG_DFL); + t = open(line, O_RDWR|O_NOCTTY); + if (t < 0) + return(-1); +# endif +# if defined(CRAY) && defined(TCVHUP) + { + register int i; + (void) signal(SIGHUP, SIG_IGN); + (void) ioctl(t, TCVHUP, (char *)0); + (void) signal(SIGHUP, SIG_DFL); + +#ifdef UNICOS7x + if (secflag) { + if (secstat(line, &secbuf) < 0) + return(-1); + if (setulvl(secbuf.st_slevel) < 0) + return(-1); + if (setucmp(secbuf.st_compart) < 0) + return(-1); + } +#endif /* UNICOS7x */ + + i = open(line, O_RDWR); + +#ifdef UNICOS7x + if (secflag) { + if (setulvl(sysv.sy_minlvl) < 0) + return(-1); + if (setucmp(0) < 0) + return(-1); + } +#endif /* UNICOS7x */ + + if (i < 0) + return(-1); + (void) close(t); + t = i; + } +# endif /* defined(CRAY) && defined(TCVHUP) */ + return(t); +} +#endif /* !defined(CRAY) || !defined(NEWINIT) */ + +#if BSD <= 43 + + int +login_tty(t) + int t; +{ + if (setsid() < 0) { +#ifdef ultrix + /* + * The setsid() may have failed because we + * already have a pgrp == pid. Zero out + * our pgrp and try again... + */ + if ((setpgrp(0, 0) < 0) || (setsid() < 0)) +#endif + fatalperror(net, "setsid()"); + } +# ifdef TIOCSCTTY + if (ioctl(t, TIOCSCTTY, (char *)0) < 0) + fatalperror(net, "ioctl(sctty)"); +# if defined(CRAY) + /* + * Close the hard fd to /dev/ttypXXX, and re-open through + * the indirect /dev/tty interface. + */ + close(t); + if ((t = open("/dev/tty", O_RDWR)) < 0) + fatalperror(net, "open(/dev/tty)"); +# endif +# else + /* + * We get our controlling tty assigned as a side-effect + * of opening up a tty device. But on BSD based systems, + * this only happens if our process group is zero. The + * setsid() call above may have set our pgrp, so clear + * it out before opening the tty... + */ +# ifndef SOLARIS + (void) setpgrp(0, 0); +# else + (void) setpgrp(); +# endif + close(open(line, O_RDWR)); +# endif + if (t != 0) + (void) dup2(t, 0); + if (t != 1) + (void) dup2(t, 1); + if (t != 2) + (void) dup2(t, 2); + if (t > 2) + close(t); + return(0); +} +#endif /* BSD <= 43 */ + +#ifdef NEWINIT +char *gen_id = "fe"; +#endif + +/* + * startslave(host) + * + * Given a hostname, do whatever + * is necessary to startup the login process on the slave side of the pty. + */ + +/* ARGSUSED */ + void +startslave(host, autologin, autoname) + char *host; + int autologin; + char *autoname; +{ + register int i; + long time(); + char name[256]; +#ifdef NEWINIT + extern char *ptyip; + struct init_request request; + void nologinproc(); + register int n; +#endif /* NEWINIT */ + +#if defined(AUTHENTICATION) + if (!autoname || !autoname[0]) + autologin = 0; + + if (autologin < auth_level) { + fatal(net, "Authorization failed"); + exit(1); + } +#endif + +#ifndef NEWINIT +# ifdef PARENT_DOES_UTMP + utmp_sig_init(); +# endif /* PARENT_DOES_UTMP */ + + if ((i = fork()) < 0) + fatalperror(net, "fork"); + if (i) { +# ifdef PARENT_DOES_UTMP + /* + * Cray parent will create utmp entry for child and send + * signal to child to tell when done. Child waits for signal + * before doing anything important. + */ + register int pid = i; + void sigjob P((int)); + + setpgrp(); + utmp_sig_reset(); /* reset handler to default */ + /* + * Create utmp entry for child + */ + (void) time(&wtmp.ut_time); + wtmp.ut_type = LOGIN_PROCESS; + wtmp.ut_pid = pid; + SCPYN(wtmp.ut_user, "LOGIN"); + SCPYN(wtmp.ut_host, host); + SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); +#ifndef __hpux + SCPYN(wtmp.ut_id, wtmp.ut_line+3); +#else + SCPYN(wtmp.ut_id, wtmp.ut_line+7); +#endif + pututline(&wtmp); + endutent(); + if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { + (void) write(i, (char *)&wtmp, sizeof(struct utmp)); + (void) close(i); + } +#ifdef CRAY + (void) signal(WJSIGNAL, sigjob); +#endif + utmp_sig_notify(pid); +# endif /* PARENT_DOES_UTMP */ + } else { + getptyslave(autologin); + start_login(host, autologin, autoname); + /*NOTREACHED*/ + } +#else /* NEWINIT */ + + /* + * Init will start up login process if we ask nicely. We only wait + * for it to start up and begin normal telnet operation. + */ + if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { + char tbuf[128]; + (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); + fatalperror(net, tbuf); + } + memset((char *)&request, 0, sizeof(request)); + request.magic = INIT_MAGIC; + SCPYN(request.gen_id, gen_id); + SCPYN(request.tty_id, &line[8]); + SCPYN(request.host, host); + SCPYN(request.term_type, terminaltype ? terminaltype : "network"); +#if !defined(UNICOS5) + request.signal = SIGCLD; + request.pid = getpid(); +#endif +#ifdef BFTPDAEMON + /* + * Are we working as the bftp daemon? + */ + if (bftpd) { + SCPYN(request.exec_name, BFTPPATH); + } +#endif /* BFTPDAEMON */ + if (write(i, (char *)&request, sizeof(request)) < 0) { + char tbuf[128]; + (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); + fatalperror(net, tbuf); + } + (void) close(i); + (void) signal(SIGALRM, nologinproc); + for (i = 0; ; i++) { + char tbuf[128]; + alarm(15); + n = read(pty, ptyip, BUFSIZ); + if (i == 3 || n >= 0 || !gotalarm) + break; + gotalarm = 0; + sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); + (void) write(net, tbuf, strlen(tbuf)); + } + if (n < 0 && gotalarm) + fatal(net, "/etc/init didn't start login process"); + pcc += n; + alarm(0); + (void) signal(SIGALRM, SIG_DFL); + + return; +#endif /* NEWINIT */ +} + +char *envinit[3]; +extern char **environ; + + void +init_env() +{ + extern char *getenv(); + char **envp; + + envp = envinit; + if (*envp = getenv("TZ")) + *envp++ -= 3; +#if defined(CRAY) || defined(__hpux) + else + *envp++ = "TZ=GMT0"; +#endif + *envp = 0; + environ = envinit; +} + +#ifndef NEWINIT + +/* + * start_login(host) + * + * Assuming that we are now running as a child processes, this + * function will turn us into the login process. + */ + + void +start_login(host, autologin, name) + char *host; + int autologin; + char *name; +{ + register char *cp; + register char **argv; + char **addarg(); + extern char *getenv(); +#ifdef UTMPX + register int pid = getpid(); + struct utmpx utmpx; +#endif +#ifdef SOLARIS + char *term; + char termbuf[64]; +#endif + +#ifdef UTMPX + /* + * Create utmp entry for child + */ + + memset(&utmpx, 0, sizeof(utmpx)); + SCPYN(utmpx.ut_user, ".telnet"); + SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); + utmpx.ut_pid = pid; + utmpx.ut_id[0] = 't'; + utmpx.ut_id[1] = 'n'; + utmpx.ut_id[2] = SC_WILDC; + utmpx.ut_id[3] = SC_WILDC; + utmpx.ut_type = LOGIN_PROCESS; + (void) time(&utmpx.ut_tv.tv_sec); + if (pututxline(&utmpx) == NULL) + fatal(net, "pututxline failed"); +#endif + + /* + * -h : pass on name of host. + * WARNING: -h is accepted by login if and only if + * getuid() == 0. + * -p : don't clobber the environment (so terminal type stays set). + * + * -f : force this login, he has already been authenticated + */ + argv = addarg(0, "login"); + +#if !defined(NO_LOGIN_H) + +# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) + /* + * Don't add the "-h host" option if we are going + * to be adding the "-r host" option down below... + */ + if ((auth_level < 0) || (autologin != AUTH_VALID)) +# endif + { + argv = addarg(argv, "-h"); + argv = addarg(argv, host); +#ifdef SOLARIS + /* + * SVR4 version of -h takes TERM= as second arg, or - + */ + term = getenv("TERM"); + if (term == NULL || term[0] == 0) { + term = "-"; + } else { + strcpy(termbuf, "TERM="); + strncat(termbuf, term, sizeof(termbuf) - 6); + term = termbuf; + } + argv = addarg(argv, term); +#endif + } +#endif +#if !defined(NO_LOGIN_P) + argv = addarg(argv, "-p"); +#endif +#ifdef LINEMODE + /* + * Set the environment variable "LINEMODE" to either + * "real" or "kludge" if we are operating in either + * real or kludge linemode. + */ + if (lmodetype == REAL_LINEMODE) + setenv("LINEMODE", "real", 1); +# ifdef KLUDGELINEMODE + else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) + setenv("LINEMODE", "kludge", 1); +# endif +#endif +#ifdef BFTPDAEMON + /* + * Are we working as the bftp daemon? If so, then ask login + * to start bftp instead of shell. + */ + if (bftpd) { + argv = addarg(argv, "-e"); + argv = addarg(argv, BFTPPATH); + } else +#endif +#if defined (SecurID) + /* + * don't worry about the -f that might get sent. + * A -s is supposed to override it anyhow. + */ + if (require_SecurID) + argv = addarg(argv, "-s"); +#endif +#if defined (AUTHENTICATION) + if (auth_level >= 0 && autologin == AUTH_VALID) { +# if !defined(NO_LOGIN_F) + argv = addarg(argv, "-f"); + argv = addarg(argv, name); +# else +# if defined(LOGIN_R) + /* + * We don't have support for "login -f", but we + * can fool /bin/login into thinking that we are + * rlogind, and allow us to log in without a + * password. The rlogin protocol expects + * local-user\0remote-user\0term/speed\0 + */ + + if (pty > 2) { + register char *cp; + char speed[128]; + int isecho, israw, xpty, len; + extern int def_rspeed; +# ifndef LOGIN_HOST + /* + * Tell login that we are coming from "localhost". + * If we passed in the real host name, then the + * user would have to allow .rhost access from + * every machine that they want authenticated + * access to work from, which sort of defeats + * the purpose of an authenticated login... + * So, we tell login that the session is coming + * from "localhost", and the user will only have + * to have "localhost" in their .rhost file. + */ +# define LOGIN_HOST "localhost" +# endif + argv = addarg(argv, "-r"); + argv = addarg(argv, LOGIN_HOST); + + xpty = pty; +# ifndef STREAMSPTY + pty = 0; +# else + ttyfd = 0; +# endif + init_termbuf(); + isecho = tty_isecho(); + israw = tty_israw(); + if (isecho || !israw) { + tty_setecho(0); /* Turn off echo */ + tty_setraw(1); /* Turn on raw */ + set_termbuf(); + } + len = strlen(name)+1; + write(xpty, name, len); + write(xpty, name, len); + sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", + (def_rspeed > 0) ? def_rspeed : 9600); + len = strlen(speed)+1; + write(xpty, speed, len); + + if (isecho || !israw) { + init_termbuf(); + tty_setecho(isecho); + tty_setraw(israw); + set_termbuf(); + if (!israw) { + /* + * Write a newline to ensure + * that login will be able to + * read the line... + */ + write(xpty, "\n", 1); + } + } + pty = xpty; + } +# else + argv = addarg(argv, name); +# endif +# endif + } else +#endif + if (getenv("USER")) { + argv = addarg(argv, getenv("USER")); +#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) + { + register char **cpp; + for (cpp = environ; *cpp; cpp++) + argv = addarg(argv, *cpp); + } +#endif + /* + * Assume that login will set the USER variable + * correctly. For SysV systems, this means that + * USER will no longer be set, just LOGNAME by + * login. (The problem is that if the auto-login + * fails, and the user then specifies a different + * account name, he can get logged in with both + * LOGNAME and USER in his environment, but the + * USER value will be wrong. + */ + unsetenv("USER"); + } +#ifdef SOLARIS + else { + char **p; + + argv = addarg(argv, ""); /* no login name */ + for (p = environ; *p; p++) { + argv = addarg(argv, *p); + } + } +#endif /* SOLARIS */ +#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) + if (pty > 2) + close(pty); +#endif + closelog(); + /* + * This sleep(1) is in here so that telnetd can + * finish up with the tty. There's a race condition + * the login banner message gets lost... + */ + sleep(1); + execv(_PATH_LOGIN, argv); + + syslog(LOG_ERR, "%s: %m\n", _PATH_LOGIN); + fatalperror(net, _PATH_LOGIN); + /*NOTREACHED*/ +} + + char ** +addarg(argv, val) + register char **argv; + register char *val; +{ + register char **cpp; + + if (argv == NULL) { + /* + * 10 entries, a leading length, and a null + */ + argv = (char **)malloc(sizeof(*argv) * 12); + if (argv == NULL) + return(NULL); + *argv++ = (char *)10; + *argv = (char *)0; + } + for (cpp = argv; *cpp; cpp++) + ; + if (cpp == &argv[(int)argv[-1]]) { + --argv; + *argv = (char *)((int)(*argv) + 10); + argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); + if (argv == NULL) + return(NULL); + argv++; + cpp = &argv[(int)argv[-1] - 10]; + } + *cpp++ = val; + *cpp = 0; + return(argv); +} +#endif /* NEWINIT */ + +/* + * cleanup() + * + * This is the routine to call when we are all through, to + * clean up anything that needs to be cleaned up. + */ + /* ARGSUSED */ + void +cleanup(sig) + int sig; +{ +#ifndef PARENT_DOES_UTMP +# if (BSD > 43) || defined(convex) + char *p; + + p = line + sizeof("/dev/") - 1; + if (logout(p)) + logwtmp(p, "", ""); + (void)chmod(line, 0666); + (void)chown(line, 0, 0); + *p = 'p'; + (void)chmod(line, 0666); + (void)chown(line, 0, 0); + (void) shutdown(net, 2); + exit(1); +# else + void rmut(); + + rmut(); + vhangup(); /* XXX */ + (void) shutdown(net, 2); + exit(1); +# endif +#else /* PARENT_DOES_UTMP */ +# ifdef NEWINIT + (void) shutdown(net, 2); + exit(1); +# else /* NEWINIT */ +# ifdef CRAY + static int incleanup = 0; + register int t; + int child_status; /* status of child process as returned by waitpid */ + int flags = WNOHANG|WUNTRACED; + + /* + * 1: Pick up the zombie, if we are being called + * as the signal handler. + * 2: If we are a nested cleanup(), return. + * 3: Try to clean up TMPDIR. + * 4: Fill in utmp with shutdown of process. + * 5: Close down the network and pty connections. + * 6: Finish up the TMPDIR cleanup, if needed. + */ + if (sig == SIGCHLD) { + while (waitpid(-1, &child_status, flags) > 0) + ; /* VOID */ + /* Check if the child process was stopped + * rather than exited. We want cleanup only if + * the child has died. + */ + if (WIFSTOPPED(child_status)) { + return; + } + } + t = sigblock(sigmask(SIGCHLD)); + if (incleanup) { + sigsetmask(t); + return; + } + incleanup = 1; + sigsetmask(t); +#ifdef UNICOS7x + if (secflag) { + /* + * We need to set ourselves back to a null + * label to clean up. + */ + + setulvl(sysv.sy_minlvl); + setucmp((long)0); + } +#endif /* UNICOS7x */ + + t = cleantmp(&wtmp); + setutent(); /* just to make sure */ +# endif /* CRAY */ + rmut(line); + close(pty); + (void) shutdown(net, 2); +# ifdef CRAY + if (t == 0) + cleantmp(&wtmp); +# endif /* CRAY */ + exit(1); +# endif /* NEWINT */ +#endif /* PARENT_DOES_UTMP */ +} + +#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) +/* + * _utmp_sig_rcv + * utmp_sig_init + * utmp_sig_wait + * These three functions are used to coordinate the handling of + * the utmp file between the server and the soon-to-be-login shell. + * The server actually creates the utmp structure, the child calls + * utmp_sig_wait(), until the server calls utmp_sig_notify() and + * signals the future-login shell to proceed. + */ +static int caught=0; /* NZ when signal intercepted */ +static void (*func)(); /* address of previous handler */ + + void +_utmp_sig_rcv(sig) + int sig; +{ + caught = 1; + (void) signal(SIGUSR1, func); +} + + void +utmp_sig_init() +{ + /* + * register signal handler for UTMP creation + */ + if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) + fatalperror(net, "telnetd/signal"); +} + + void +utmp_sig_reset() +{ + (void) signal(SIGUSR1, func); /* reset handler to default */ +} + +# ifdef __hpux +# define sigoff() /* do nothing */ +# define sigon() /* do nothing */ +# endif + + void +utmp_sig_wait() +{ + /* + * Wait for parent to write our utmp entry. + */ + sigoff(); + while (caught == 0) { + pause(); /* wait until we get a signal (sigon) */ + sigoff(); /* turn off signals while we check caught */ + } + sigon(); /* turn on signals again */ +} + + void +utmp_sig_notify(pid) +{ + kill(pid, SIGUSR1); +} + +# ifdef CRAY +static int gotsigjob = 0; + + /*ARGSUSED*/ + void +sigjob(sig) + int sig; +{ + register int jid; + register struct jobtemp *jp; + + while ((jid = waitjob(NULL)) != -1) { + if (jid == 0) { + return; + } + gotsigjob++; + jobend(jid, NULL, NULL); + } +} + +/* + * jid_getutid: + * called by jobend() before calling cleantmp() + * to find the correct $TMPDIR to cleanup. + */ + + struct utmp * +jid_getutid(jid) + int jid; +{ + struct utmp *cur = NULL; + + setutent(); /* just to make sure */ + while (cur = getutent()) { + if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { + return(cur); + } + } + + return(0); +} + +/* + * Clean up the TMPDIR that login created. + * The first time this is called we pick up the info + * from the utmp. If the job has already gone away, + * then we'll clean up and be done. If not, then + * when this is called the second time it will wait + * for the signal that the job is done. + */ + int +cleantmp(wtp) + register struct utmp *wtp; +{ + struct utmp *utp; + static int first = 1; + register int mask, omask, ret; + extern struct utmp *getutid P((const struct utmp *_Id)); + + + mask = sigmask(WJSIGNAL); + + if (first == 0) { + omask = sigblock(mask); + while (gotsigjob == 0) + sigpause(omask); + return(1); + } + first = 0; + setutent(); /* just to make sure */ + + utp = getutid(wtp); + if (utp == 0) { + syslog(LOG_ERR, "Can't get /var/run/utmp entry to clean TMPDIR"); + return(-1); + } + /* + * Nothing to clean up if the user shell was never started. + */ + if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) + return(1); + + /* + * Block the WJSIGNAL while we are in jobend(). + */ + omask = sigblock(mask); + ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); + sigsetmask(omask); + return(ret); +} + + int +jobend(jid, path, user) + register int jid; + register char *path; + register char *user; +{ + static int saved_jid = 0; + static int pty_saved_jid = 0; + static char saved_path[sizeof(wtmp.ut_tpath)+1]; + static char saved_user[sizeof(wtmp.ut_user)+1]; + + /* + * this little piece of code comes into play + * only when ptyreconnect is used to reconnect + * to an previous session. + * + * this is the only time when the + * "saved_jid != jid" code is executed. + */ + + if ( saved_jid && saved_jid != jid ) { + if (!path) { /* called from signal handler */ + pty_saved_jid = jid; + } else { + pty_saved_jid = saved_jid; + } + } + + if (path) { + strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); + strncpy(saved_user, user, sizeof(wtmp.ut_user)); + saved_path[sizeof(saved_path)] = '\0'; + saved_user[sizeof(saved_user)] = '\0'; + } + if (saved_jid == 0) { + saved_jid = jid; + return(0); + } + + /* if the jid has changed, get the correct entry from the utmp file */ + + if ( saved_jid != jid ) { + struct utmp *utp = NULL; + struct utmp *jid_getutid(); + + utp = jid_getutid(pty_saved_jid); + + if (utp == 0) { + syslog(LOG_ERR, "Can't get /var/run/utmp entry to clean TMPDIR"); + return(-1); + } + + cleantmpdir(jid, utp->ut_tpath, utp->ut_user); + return(1); + } + + cleantmpdir(jid, saved_path, saved_user); + return(1); +} + +/* + * Fork a child process to clean up the TMPDIR + */ +cleantmpdir(jid, tpath, user) + register int jid; + register char *tpath; + register char *user; +{ + switch(fork()) { + case -1: + syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", + tpath); + break; + case 0: + execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); + syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", + tpath, CLEANTMPCMD); + exit(1); + default: + /* + * Forget about child. We will exit, and + * /etc/init will pick it up. + */ + break; + } +} +# endif /* CRAY */ +#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ + +/* + * rmut() + * + * This is the function called by cleanup() to + * remove the utmp entry for this person. + */ + +#ifdef UTMPX + void +rmut() +{ + register f; + int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; + + struct utmpx *utxp, utmpx; + + /* + * This updates the utmpx and utmp entries and make a wtmp/x entry + */ + + SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); + utxp = getutxline(&utmpx); + if (utxp) { + utxp->ut_type = DEAD_PROCESS; + utxp->ut_exit.e_termination = 0; + utxp->ut_exit.e_exit = 0; + (void) time(&utmpx.ut_tv.tv_sec); + utmpx.ut_tv.tv_usec = 0; + modutx(utxp); + } + endutxent(); +} /* end of rmut */ +#endif + +#if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 + void +rmut() +{ + register f; + int found = 0; + struct utmp *u, *utmp; + int nutmp; + struct stat statbf; + + f = open(utmpf, O_RDWR); + if (f >= 0) { + (void) fstat(f, &statbf); + utmp = (struct utmp *)malloc((unsigned)statbf.st_size); + if (!utmp) + syslog(LOG_ERR, "utmp malloc failed"); + if (statbf.st_size && utmp) { + nutmp = read(f, (char *)utmp, (int)statbf.st_size); + nutmp /= sizeof(struct utmp); + + for (u = utmp ; u < &utmp[nutmp] ; u++) { + if (SCMPN(u->ut_line, line+5) || + u->ut_name[0]==0) + continue; + (void) lseek(f, ((long)u)-((long)utmp), L_SET); + SCPYN(u->ut_name, ""); + SCPYN(u->ut_host, ""); + (void) time(&u->ut_time); + (void) write(f, (char *)u, sizeof(wtmp)); + found++; + } + } + (void) close(f); + } + if (found) { + f = open(wtmpf, O_WRONLY|O_APPEND); + if (f >= 0) { + SCPYN(wtmp.ut_line, line+5); + SCPYN(wtmp.ut_name, ""); + SCPYN(wtmp.ut_host, ""); + (void) time(&wtmp.ut_time); + (void) write(f, (char *)&wtmp, sizeof(wtmp)); + (void) close(f); + } + } + (void) chmod(line, 0666); + (void) chown(line, 0, 0); + line[strlen("/dev/")] = 'p'; + (void) chmod(line, 0666); + (void) chown(line, 0, 0); +} /* end of rmut */ +#endif /* CRAY */ + +#ifdef __hpux +rmut (line) +char *line; +{ + struct utmp utmp; + struct utmp *utptr; + int fd; /* for /etc/wtmp */ + + utmp.ut_type = USER_PROCESS; + (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); + (void) setutent(); + utptr = getutid(&utmp); + /* write it out only if it exists */ + if (utptr) { + utptr->ut_type = DEAD_PROCESS; + utptr->ut_time = time((long *) 0); + (void) pututline(utptr); + /* set wtmp entry if wtmp file exists */ + if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { + (void) write(fd, utptr, sizeof(utmp)); + (void) close(fd); + } + } + (void) endutent(); + + (void) chmod(line, 0666); + (void) chown(line, 0, 0); + line[14] = line[13]; + line[13] = line[12]; + line[8] = 'm'; + line[9] = '/'; + line[10] = 'p'; + line[11] = 't'; + line[12] = 'y'; + (void) chmod(line, 0666); + (void) chown(line, 0, 0); +} +#endif diff --git a/telnetd.tproj/telnetd.8 b/telnetd.tproj/telnetd.8 new file mode 100644 index 0000000..f618385 --- /dev/null +++ b/telnetd.tproj/telnetd.8 @@ -0,0 +1,607 @@ +.\" Copyright (c) 1983, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt TELNETD 8 +.Os BSD 4.2 +.Sh NAME +.Nm telnetd +.Nd DARPA +.Tn TELNET +protocol server +.Sh SYNOPSIS +.Nm /usr/libexec/telnetd +.Op Fl BUhlkns +.Op Fl D Ar debugmode +.Op Fl I Ns Ar initid +.Op Fl S Ar tos +.Op Fl X Ar authtype +.Op Fl a Ar authmode +.Op Fl edebug +.Op Fl r Ns Ar lowpty-highpty +.Op Fl u Ar len +.Op Fl debug Op Ar port +.Sh DESCRIPTION +The +.Nm telnetd +command is a server which supports the +.Tn DARPA +standard +.Tn TELNET +virtual terminal protocol. +.Nm Telnetd +is normally invoked by the internet server (see +.Xr inetd 8 ) +for requests to connect to the +.Tn TELNET +port as indicated by the +.Pa /etc/services +file (see +.Xr services 5 ) . +The +.Fl debug +option may be used to start up +.Nm telnetd +manually, instead of through +.Xr inetd 8 . +If started up this way, +.Ar port +may be specified to run +.Nm telnetd +on an alternate +.Tn TCP +port number. +.Pp +The +.Nm telnetd +command accepts the following options: +.Bl -tag -width "-a authmode" +.It Fl a Ar authmode +This option may be used for specifying what mode should +be used for authentication. +Note that this option is only useful if +.Nm telnetd +has been compiled with support for the +.Dv AUTHENTICATION +option. +There are several valid values for +.Ar authmode: +.Bl -tag -width debug +.It debug +Turns on authentication debugging code. +.It user +Only allow connections when the remote user +can provide valid authentication information +to identify the remote user, +and is allowed access to the specified account +without providing a password. +.It valid +Only allow connections when the remote user +can provide valid authentication information +to identify the remote user. +The +.Xr login 1 +command will provide any additional user verification +needed if the remote user is not allowed automatic +access to the specified account. +.It other +Only allow connections that supply some authentication information. +This option is currently not supported +by any of the existing authentication mechanisms, +and is thus the same as specifying +.Fl a +.Cm valid . +.It none +This is the default state. +Authentication information is not required. +If no or insufficient authentication information +is provided, then the +.Xr login 1 +program will provide the necessary user +verification. +.It off +This disables the authentication code. +All user verification will happen through the +.Xr login 1 +program. +.El +.It Fl B +Specifies bftp server mode. In this mode, +.Nm telnetd +causes login to start a +.Xr bftp 1 +session rather than the user's +normal shell. In bftp daemon mode normal +logins are not supported, and it must be used +on a port other than the normal +.Tn TELNET +port. +.It Fl D Ar debugmode +This option may be used for debugging purposes. +This allows +.Nm telnetd +to print out debugging information +to the connection, allowing the user to see what +.Nm telnetd +is doing. +There are several possible values for +.Ar debugmode: +.Bl -tag -width exercise +.It Cm options +Prints information about the negotiation of +.Tn TELNET +options. +.It Cm report +Prints the +.Cm options +information, plus some additional information +about what processing is going on. +.It Cm netdata +Displays the data stream received by +.Nm telnetd. +.It Cm ptydata +Displays data written to the pty. +.It Cm exercise +Has not been implemented yet. +.El +.It Fl debug +Enables debugging on each socket created by +.Nm telnetd +(see +.Dv SO_DEBUG +in +.Xr socket 2 ) . +.It Fl edebug +If +.Nm telnetd +has been compiled with support for data encryption, then the +.Fl edebug +option may be used to enable encryption debugging code. +.It Fl h +Disables the printing of host-specific information before +login has been completed. +.It Fl I Ar initid +This option is only applicable to +.Tn UNICOS +systems prior to 7.0. +It specifies the +.Dv ID +from +.Pa /etc/inittab +to use when init starts login sessions. The default +.Dv ID +is +.Dv fe. +.It Fl k +This option is only useful if +.Nm telnetd +has been compiled with both linemode and kludge linemode +support. If the +.Fl k +option is specified, then if the remote client does not +support the +.Dv LINEMODE +option, then +.Nm telnetd +will operate in character at a time mode. +It will still support kludge linemode, but will only +go into kludge linemode if the remote client requests +it. +(This is done by by the client sending +.Dv DONT SUPPRESS-GO-AHEAD +and +.Dv DONT ECHO . ) +The +.Fl k +option is most useful when there are remote clients +that do not support kludge linemode, but pass the heuristic +(if they respond with +.Dv WILL TIMING-MARK +in response to a +.Dv DO TIMING-MARK) +for kludge linemode support. +.It Fl l +Specifies line mode. Tries to force clients to use line- +at-a-time mode. +If the +.Dv LINEMODE +option is not supported, it will go +into kludge linemode. +.It Fl n +Disable +.Dv TCP +keep-alives. Normally +.Nm telnetd +enables the +.Tn TCP +keep-alive mechanism to probe connections that +have been idle for some period of time to determine +if the client is still there, so that idle connections +from machines that have crashed or can no longer +be reached may be cleaned up. +.It Fl r Ar lowpty-highpty +This option is only enabled when +.Nm telnetd +is compiled for +.Dv UNICOS. +It specifies an inclusive range of pseudo-terminal devices to +use. If the system has sysconf variable +.Dv _SC_CRAY_NPTY +configured, the default pty search range is 0 to +.Dv _SC_CRAY_NPTY; +otherwise, the default range is 0 to 128. Either +.Ar lowpty +or +.Ar highpty +may be omitted to allow changing +either end of the search range. If +.Ar lowpty +is omitted, the - character is still required so that +.Nm telnetd +can differentiate +.Ar highpty +from +.Ar lowpty . +.It Fl s +This option is only enabled if +.Nm telnetd +is compiled with support for +.Tn SecurID +cards. +It causes the +.Fl s +option to be passed on to +.Xr login 1 , +and thus is only useful if +.Xr login 1 +supports the +.Fl s +flag to indicate that only +.Tn SecurID +validated logins are allowed, and is +usually useful for controlling remote logins +from outside of a firewall. +.It Fl S Ar tos +.It Fl u Ar len +This option is used to specify the size of the field +in the +.Dv utmp +structure that holds the remote host name. +If the resolved host name is longer than +.Ar len , +the dotted decimal value will be used instead. +This allows hosts with very long host names that +overflow this field to still be uniquely identified. +Specifying +.Fl u0 +indicates that only dotted decimal addresses +should be put into the +.Pa utmp +file. +.ne 1i +.It Fl U +This option causes +.Nm telnetd +to refuse connections from addresses that +cannot be mapped back into a symbolic name +via the +.Xr gethostbyaddr 3 +routine. +.It Fl X Ar authtype +This option is only valid if +.Nm telnetd +has been built with support for the authentication option. +It disables the use of +.Ar authtype +authentication, and +can be used to temporarily disable +a specific authentication type without having to recompile +.Nm telnetd . +.El +.Pp +.Nm Telnetd +operates by allocating a pseudo-terminal device (see +.Xr pty 4 ) +for a client, then creating a login process which has +the slave side of the pseudo-terminal as +.Dv stdin , +.Dv stdout +and +.Dv stderr . +.Nm Telnetd +manipulates the master side of the pseudo-terminal, +implementing the +.Tn TELNET +protocol and passing characters +between the remote client and the login process. +.Pp +When a +.Tn TELNET +session is started up, +.Nm telnetd +sends +.Tn TELNET +options to the client side indicating +a willingness to do the +following +.Tn TELNET +options, which are described in more detail below: +.Bd -literal -offset indent +DO AUTHENTICATION +WILL ENCRYPT +DO TERMINAL TYPE +DO TSPEED +DO XDISPLOC +DO NEW-ENVIRON +DO ENVIRON +WILL SUPPRESS GO AHEAD +DO ECHO +DO LINEMODE +DO NAWS +WILL STATUS +DO LFLOW +DO TIMING-MARK +.Ed +.Pp +The pseudo-terminal allocated to the client is configured +to operate in \*(lqcooked\*(rq mode, and with +.Dv XTABS and +.Dv CRMOD +enabled (see +.Xr tty 4 ) . +.Pp +.Nm Telnetd +has support for enabling locally the following +.Tn TELNET +options: +.Bl -tag -width "DO AUTHENTICATION" +.It "WILL ECHO" +When the +.Dv LINEMODE +option is enabled, a +.Dv WILL ECHO +or +.Dv WONT ECHO +will be sent to the client to indicate the +current state of terminal echoing. +When terminal echo is not desired, a +.Dv WILL ECHO +is sent to indicate that +.Tn telnetd +will take care of echoing any data that needs to be +echoed to the terminal, and then nothing is echoed. +When terminal echo is desired, a +.Dv WONT ECHO +is sent to indicate that +.Tn telnetd +will not be doing any terminal echoing, so the +client should do any terminal echoing that is needed. +.It "WILL BINARY" +Indicates that the client is willing to send a +8 bits of data, rather than the normal 7 bits +of the Network Virtual Terminal. +.It "WILL SGA" +Indicates that it will not be sending +.Dv IAC GA, +go ahead, commands. +.It "WILL STATUS" +Indicates a willingness to send the client, upon +request, of the current status of all +.Tn TELNET +options. +.It "WILL TIMING-MARK" +Whenever a +.Dv DO TIMING-MARK +command is received, it is always responded +to with a +.Dv WILL TIMING-MARK +.ne 1i +.It "WILL LOGOUT" +When a +.Dv DO LOGOUT +is received, a +.Dv WILL LOGOUT +is sent in response, and the +.Tn TELNET +session is shut down. +.It "WILL ENCRYPT" +Only sent if +.Nm telnetd +is compiled with support for data encryption, and +indicates a willingness to decrypt +the data stream. +.El +.Pp +.Nm Telnetd +has support for enabling remotely the following +.Tn TELNET +options: +.Bl -tag -width "DO AUTHENTICATION" +.It "DO BINARY" +Sent to indicate that +.Tn telnetd +is willing to receive an 8 bit data stream. +.It "DO LFLOW" +Requests that the client handle flow control +characters remotely. +.It "DO ECHO" +This is not really supported, but is sent to identify a 4.2BSD +.Xr telnet 1 +client, which will improperly respond with +.Dv WILL ECHO. +If a +.Dv WILL ECHO +is received, a +.Dv DONT ECHO +will be sent in response. +.It "DO TERMINAL-TYPE" +Indicates a desire to be able to request the +name of the type of terminal that is attached +to the client side of the connection. +.It "DO SGA" +Indicates that it does not need to receive +.Dv IAC GA, +the go ahead command. +.It "DO NAWS" +Requests that the client inform the server when +the window (display) size changes. +.It "DO TERMINAL-SPEED" +Indicates a desire to be able to request information +about the speed of the serial line to which +the client is attached. +.It "DO XDISPLOC" +Indicates a desire to be able to request the name +of the X windows display that is associated with +the telnet client. +.It "DO NEW-ENVIRON" +Indicates a desire to be able to request environment +variable information, as described in RFC 1572. +.It "DO ENVIRON" +Indicates a desire to be able to request environment +variable information, as described in RFC 1408. +.It "DO LINEMODE" +Only sent if +.Nm telnetd +is compiled with support for linemode, and +requests that the client do line by line processing. +.It "DO TIMING-MARK" +Only sent if +.Nm telnetd +is compiled with support for both linemode and +kludge linemode, and the client responded with +.Dv WONT LINEMODE. +If the client responds with +.Dv WILL TM, +the it is assumed that the client supports +kludge linemode. +Note that the +.Op Fl k +option can be used to disable this. +.It "DO AUTHENTICATION" +Only sent if +.Nm telnetd +is compiled with support for authentication, and +indicates a willingness to receive authentication +information for automatic login. +.It "DO ENCRYPT" +Only sent if +.Nm telnetd +is compiled with support for data encryption, and +indicates a willingness to decrypt +the data stream. +.Sh ENVIRONMENT +.Sh FILES +.Pa /etc/services +.br +.Pa /etc/inittab +(UNICOS systems only) +.br +.Pa /etc/iptos +(if supported) +.br +.Pa /usr/ucb/bftp +(if supported) +.Sh "SEE ALSO" +.Xr telnet 1 , +.Xr login 1 , +.Xr bftp 1 +(if supported) +.Sh STANDARDS +.Bl -tag -compact -width RFC-1572 +.It Cm RFC-854 +.Tn TELNET +PROTOCOL SPECIFICATION +.It Cm RFC-855 +TELNET OPTION SPECIFICATIONS +.It Cm RFC-856 +TELNET BINARY TRANSMISSION +.It Cm RFC-857 +TELNET ECHO OPTION +.It Cm RFC-858 +TELNET SUPPRESS GO AHEAD OPTION +.It Cm RFC-859 +TELNET STATUS OPTION +.It Cm RFC-860 +TELNET TIMING MARK OPTION +.It Cm RFC-861 +TELNET EXTENDED OPTIONS - LIST OPTION +.It Cm RFC-885 +TELNET END OF RECORD OPTION +.It Cm RFC-1073 +Telnet Window Size Option +.It Cm RFC-1079 +Telnet Terminal Speed Option +.It Cm RFC-1091 +Telnet Terminal-Type Option +.It Cm RFC-1096 +Telnet X Display Location Option +.It Cm RFC-1123 +Requirements for Internet Hosts -- Application and Support +.It Cm RFC-1184 +Telnet Linemode Option +.It Cm RFC-1372 +Telnet Remote Flow Control Option +.It Cm RFC-1416 +Telnet Authentication Option +.It Cm RFC-1411 +Telnet Authentication: Kerberos Version 4 +.It Cm RFC-1412 +Telnet Authentication: SPX +.It Cm RFC-1571 +Telnet Environment Option Interoperability Issues +.It Cm RFC-1572 +Telnet Environment Option +.Sh BUGS +Some +.Tn TELNET +commands are only partially implemented. +.Pp +Because of bugs in the original 4.2 BSD +.Xr telnet 1 , +.Nm telnetd +performs some dubious protocol exchanges to try to discover if the remote +client is, in fact, a 4.2 BSD +.Xr telnet 1 . +.Pp +Binary mode +has no common interpretation except between similar operating systems +(Unix in this case). +.Pp +The terminal type name received from the remote client is converted to +lower case. +.Pp +.Nm Telnetd +never sends +.Tn TELNET +.Dv IAC GA +(go ahead) commands. diff --git a/telnetd.tproj/telnetd.c b/telnetd.tproj/telnetd.c new file mode 100644 index 0000000..01943a4 --- /dev/null +++ b/telnetd.tproj/telnetd.c @@ -0,0 +1,1640 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include "telnetd.h" +#include "pathnames.h" + +#if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) +/* + * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can + * use it to tell us to turn off all the socket security code, + * since that is only used in UNICOS 7.0 and later. + */ +# undef _SC_CRAY_SECURE_SYS +#endif + +#if defined(_SC_CRAY_SECURE_SYS) +#include +#include +# ifdef SO_SEC_MULTI /* 8.0 code */ +#include +#include +# endif /* SO_SEC_MULTI */ +int secflag; +char tty_dev[16]; +struct secdev dv; +struct sysv sysv; +# ifdef SO_SEC_MULTI /* 8.0 code */ +struct socksec ss; +# else /* SO_SEC_MULTI */ /* 7.0 code */ +struct socket_security ss; +# endif /* SO_SEC_MULTI */ +#endif /* _SC_CRAY_SECURE_SYS */ + +#if defined(AUTHENTICATION) +#include +int auth_level = 0; +#endif +#if defined(SecurID) +int require_SecurID = 0; +#endif + +extern int utmp_len; +int registerd_host_only = 0; + +#ifdef STREAMSPTY +# include +# include +/* make sure we don't get the bsd version */ +# include "/usr/include/sys/tty.h" +# include + +/* + * Because of the way ptyibuf is used with streams messages, we need + * ptyibuf+1 to be on a full-word boundary. The following wierdness + * is simply to make that happen. + */ +long ptyibufbuf[BUFSIZ/sizeof(long)+1]; +char *ptyibuf = ((char *)&ptyibufbuf[1])-1; +char *ptyip = ((char *)&ptyibufbuf[1])-1; +char ptyibuf2[BUFSIZ]; +unsigned char ctlbuf[BUFSIZ]; +struct strbuf strbufc, strbufd; + +int readstream(); + +#else /* ! STREAMPTY */ + +/* + * I/O data buffers, + * pointers, and counters. + */ +char ptyibuf[BUFSIZ], *ptyip = ptyibuf; +char ptyibuf2[BUFSIZ]; + +#endif /* ! STREAMPTY */ + +int hostinfo = 1; /* do we print login banner? */ + +#ifdef CRAY +extern int newmap; /* nonzero if \n maps to ^M^J */ +int lowpty = 0, highpty; /* low, high pty numbers */ +#endif /* CRAY */ + +int debug = 0; +int keepalive = 1; +char *progname; + +extern void usage P((void)); +void doit(struct sockaddr_in *); +int terminaltypeok(char *); +void startslave(char *, int, char *); + + +/* + * The string to pass to getopt(). We do it this way so + * that only the actual options that we support will be + * passed off to getopt(). + */ +char valid_opts[] = { + 'd', ':', 'h', 'k', 'n', 'S', ':', 'u', ':', 'U', +#ifdef AUTHENTICATION + 'a', ':', 'X', ':', +#endif +#ifdef BFTPDAEMON + 'B', +#endif +#ifdef DIAGNOSTICS + 'D', ':', +#endif +#ifdef ENCRYPTION + 'e', ':', +#endif +#if defined(CRAY) && defined(NEWINIT) + 'I', ':', +#endif +#ifdef LINEMODE + 'l', +#endif +#ifdef CRAY + 'r', ':', +#endif +#ifdef SecurID + 's', +#endif + '\0' +}; + +int +main(argc, argv) + char *argv[]; +{ + struct sockaddr_in from; + int on = 1, fromlen; + register int ch; + extern char *optarg; + extern int optind; +#if defined(IPPROTO_IP) && defined(IP_TOS) + int tos = -1; +#endif + + pfrontp = pbackp = ptyobuf; + netip = netibuf; + nfrontp = nbackp = netobuf; +#ifdef ENCRYPTION + nclearto = 0; +#endif /* ENCRYPTION */ + + progname = *argv; + +#ifdef CRAY + /* + * Get number of pty's before trying to process options, + * which may include changing pty range. + */ + highpty = getnpty(); +#endif /* CRAY */ + + while ((ch = getopt(argc, argv, valid_opts)) != EOF) { + switch(ch) { + +#ifdef AUTHENTICATION + case 'a': + /* + * Check for required authentication level + */ + if (strcmp(optarg, "debug") == 0) { + extern int auth_debug_mode; + auth_debug_mode = 1; + } else if (strcasecmp(optarg, "none") == 0) { + auth_level = 0; + } else if (strcasecmp(optarg, "other") == 0) { + auth_level = AUTH_OTHER; + } else if (strcasecmp(optarg, "user") == 0) { + auth_level = AUTH_USER; + } else if (strcasecmp(optarg, "valid") == 0) { + auth_level = AUTH_VALID; + } else if (strcasecmp(optarg, "off") == 0) { + /* + * This hack turns off authentication + */ + auth_level = -1; + } else { + fprintf(stderr, + "telnetd: unknown authorization level for -a\n"); + } + break; +#endif /* AUTHENTICATION */ + +#ifdef BFTPDAEMON + case 'B': + bftpd++; + break; +#endif /* BFTPDAEMON */ + + case 'd': + if (strcmp(optarg, "ebug") == 0) { + debug++; + break; + } + usage(); + /* NOTREACHED */ + break; + +#ifdef DIAGNOSTICS + case 'D': + /* + * Check for desired diagnostics capabilities. + */ + if (!strcmp(optarg, "report")) { + diagnostic |= TD_REPORT|TD_OPTIONS; + } else if (!strcmp(optarg, "exercise")) { + diagnostic |= TD_EXERCISE; + } else if (!strcmp(optarg, "netdata")) { + diagnostic |= TD_NETDATA; + } else if (!strcmp(optarg, "ptydata")) { + diagnostic |= TD_PTYDATA; + } else if (!strcmp(optarg, "options")) { + diagnostic |= TD_OPTIONS; + } else { + usage(); + /* NOT REACHED */ + } + break; +#endif /* DIAGNOSTICS */ + +#ifdef ENCRYPTION + case 'e': + if (strcmp(optarg, "debug") == 0) { + extern int encrypt_debug_mode; + encrypt_debug_mode = 1; + break; + } + usage(); + /* NOTREACHED */ + break; +#endif /* ENCRYPTION */ + + case 'h': + hostinfo = 0; + break; + +#if defined(CRAY) && defined(NEWINIT) + case 'I': + { + extern char *gen_id; + gen_id = optarg; + break; + } +#endif /* defined(CRAY) && defined(NEWINIT) */ + +#ifdef LINEMODE + case 'l': + alwayslinemode = 1; + break; +#endif /* LINEMODE */ + + case 'k': +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + lmodetype = NO_AUTOKLUDGE; +#else + /* ignore -k option if built without kludge linemode */ +#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ + break; + + case 'n': + keepalive = 0; + break; + +#ifdef CRAY + case 'r': + { + char *strchr(); + char *c; + + /* + * Allow the specification of alterations + * to the pty search range. It is legal to + * specify only one, and not change the + * other from its default. + */ + c = strchr(optarg, '-'); + if (c) { + *c++ = '\0'; + highpty = atoi(c); + } + if (*optarg != '\0') + lowpty = atoi(optarg); + if ((lowpty > highpty) || (lowpty < 0) || + (highpty > 32767)) { + usage(); + /* NOT REACHED */ + } + break; + } +#endif /* CRAY */ + +#ifdef SecurID + case 's': + /* SecurID required */ + require_SecurID = 1; + break; +#endif /* SecurID */ + case 'S': +#ifdef HAS_GETTOS + if ((tos = parsetos(optarg, "tcp")) < 0) + fprintf(stderr, "%s%s%s\n", + "telnetd: Bad TOS argument '", optarg, + "'; will try to use default TOS"); +#else + fprintf(stderr, "%s%s\n", "TOS option unavailable; ", + "-S flag not supported\n"); +#endif + break; + + case 'u': + utmp_len = atoi(optarg); + break; + + case 'U': + registerd_host_only = 1; + break; + +#ifdef AUTHENTICATION + case 'X': + /* + * Check for invalid authentication types + */ + auth_disable_name(optarg); + break; +#endif /* AUTHENTICATION */ + + default: + fprintf(stderr, "telnetd: %c: unknown option\n", ch); + /* FALLTHROUGH */ + case '?': + usage(); + /* NOTREACHED */ + } + } + + argc -= optind; + argv += optind; + + if (debug) { + int s, ns, foo; + struct servent *sp; + static struct sockaddr_in sin = { AF_INET }; + + if (argc > 1) { + usage(); + /* NOT REACHED */ + } else if (argc == 1) { + if (sp = getservbyname(*argv, "tcp")) { + sin.sin_port = sp->s_port; + } else { + sin.sin_port = atoi(*argv); + if ((int)sin.sin_port <= 0) { + fprintf(stderr, "telnetd: %s: bad port #\n", *argv); + usage(); + /* NOT REACHED */ + } + sin.sin_port = htons((u_short)sin.sin_port); + } + } else { + sp = getservbyname("telnet", "tcp"); + if (sp == 0) { + fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); + exit(1); + } + sin.sin_port = sp->s_port; + } + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("telnetd: socket");; + exit(1); + } + (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)); + if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { + perror("bind"); + exit(1); + } + if (listen(s, 1) < 0) { + perror("listen"); + exit(1); + } + foo = sizeof sin; + ns = accept(s, (struct sockaddr *)&sin, &foo); + if (ns < 0) { + perror("accept"); + exit(1); + } + (void) dup2(ns, 0); + (void) close(ns); + (void) close(s); +#ifdef convex + } else if (argc == 1) { + ; /* VOID*/ /* Just ignore the host/port name */ +#endif + } else if (argc > 0) { + usage(); + /* NOT REACHED */ + } + +#if defined(_SC_CRAY_SECURE_SYS) + secflag = sysconf(_SC_CRAY_SECURE_SYS); + + /* + * Get socket's security label + */ + if (secflag) { + int szss = sizeof(ss); +#ifdef SO_SEC_MULTI /* 8.0 code */ + int sock_multi; + int szi = sizeof(int); +#endif /* SO_SEC_MULTI */ + + memset((char *)&dv, 0, sizeof(dv)); + + if (getsysv(&sysv, sizeof(struct sysv)) != 0) { + perror("getsysv"); + exit(1); + } + + /* + * Get socket security label and set device values + * {security label to be set on ttyp device} + */ +#ifdef SO_SEC_MULTI /* 8.0 code */ + if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, + (char *)&ss, &szss) < 0) || + (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, + (char *)&sock_multi, &szi) < 0)) { + perror("getsockopt"); + exit(1); + } else { + dv.dv_actlvl = ss.ss_actlabel.lt_level; + dv.dv_actcmp = ss.ss_actlabel.lt_compart; + if (!sock_multi) { + dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; + dv.dv_valcmp = dv.dv_actcmp; + } else { + dv.dv_minlvl = ss.ss_minlabel.lt_level; + dv.dv_maxlvl = ss.ss_maxlabel.lt_level; + dv.dv_valcmp = ss.ss_maxlabel.lt_compart; + } + dv.dv_devflg = 0; + } +#else /* SO_SEC_MULTI */ /* 7.0 code */ + if (getsockopt(0, SOL_SOCKET, SO_SECURITY, + (char *)&ss, &szss) >= 0) { + dv.dv_actlvl = ss.ss_slevel; + dv.dv_actcmp = ss.ss_compart; + dv.dv_minlvl = ss.ss_minlvl; + dv.dv_maxlvl = ss.ss_maxlvl; + dv.dv_valcmp = ss.ss_maxcmp; + } +#endif /* SO_SEC_MULTI */ + } +#endif /* _SC_CRAY_SECURE_SYS */ + + openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); + fromlen = sizeof (from); + if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { + fprintf(stderr, "%s: ", progname); + perror("getpeername"); + _exit(1); + } + if (keepalive && + setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, + (char *)&on, sizeof (on)) < 0) { + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); + } + +#if defined(IPPROTO_IP) && defined(IP_TOS) + { +# if defined(HAS_GETTOS) + struct tosent *tp; + if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) + tos = tp->t_tos; +# endif + if (tos < 0) + tos = 020; /* Low Delay bit */ + if (tos + && (setsockopt(0, IPPROTO_IP, IP_TOS, + (char *)&tos, sizeof(tos)) < 0) + && (errno != ENOPROTOOPT) ) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + } +#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ + net = 0; + doit(&from); + /* NOTREACHED */ + exit(0); +} /* end of main */ + + void +usage() +{ + fprintf(stderr, "Usage: telnetd"); +#ifdef AUTHENTICATION + fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); +#endif +#ifdef BFTPDAEMON + fprintf(stderr, " [-B]"); +#endif + fprintf(stderr, " [-debug]"); +#ifdef DIAGNOSTICS + fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); +#endif +#ifdef AUTHENTICATION + fprintf(stderr, " [-edebug]"); +#endif + fprintf(stderr, " [-h]"); +#if defined(CRAY) && defined(NEWINIT) + fprintf(stderr, " [-Iinitid]"); +#endif +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + fprintf(stderr, " [-k]"); +#endif +#ifdef LINEMODE + fprintf(stderr, " [-l]"); +#endif + fprintf(stderr, " [-n]"); +#ifdef CRAY + fprintf(stderr, " [-r[lowpty]-[highpty]]"); +#endif + fprintf(stderr, "\n\t"); +#ifdef SecurID + fprintf(stderr, " [-s]"); +#endif +#ifdef HAS_GETTOS + fprintf(stderr, " [-S tos]"); +#endif +#ifdef AUTHENTICATION + fprintf(stderr, " [-X auth-type]"); +#endif + fprintf(stderr, " [-u utmp_hostname_length] [-U]"); + fprintf(stderr, " [port]\n"); + exit(1); +} + +/* + * getterminaltype + * + * Ask the other end to send along its terminal type and speed. + * Output is the variable terminaltype filled in. + */ +static unsigned char ttytype_sbbuf[] = { + IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE +}; + + int +getterminaltype(name) + char *name; +{ + int retval = -1; + void _gettermname(); + + settimer(baseline); +#if defined(AUTHENTICATION) + /* + * Handle the Authentication option before we do anything else. + */ + send_do(TELOPT_AUTHENTICATION, 1); + while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) + ttloop(); + if (his_state_is_will(TELOPT_AUTHENTICATION)) { + retval = auth_wait(name); + } +#endif + +#ifdef ENCRYPTION + send_will(TELOPT_ENCRYPT, 1); +#endif /* ENCRYPTION */ + send_do(TELOPT_TTYPE, 1); + send_do(TELOPT_TSPEED, 1); + send_do(TELOPT_XDISPLOC, 1); + send_do(TELOPT_NEW_ENVIRON, 1); + send_do(TELOPT_OLD_ENVIRON, 1); + while ( +#ifdef ENCRYPTION + his_do_dont_is_changing(TELOPT_ENCRYPT) || +#endif /* ENCRYPTION */ + his_will_wont_is_changing(TELOPT_TTYPE) || + his_will_wont_is_changing(TELOPT_TSPEED) || + his_will_wont_is_changing(TELOPT_XDISPLOC) || + his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || + his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { + ttloop(); + } +#ifdef ENCRYPTION + /* + * Wait for the negotiation of what type of encryption we can + * send with. If autoencrypt is not set, this will just return. + */ + if (his_state_is_will(TELOPT_ENCRYPT)) { + encrypt_wait(); + } +#endif /* ENCRYPTION */ + if (his_state_is_will(TELOPT_TSPEED)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; + + memmove(nfrontp, sb, sizeof sb); + nfrontp += sizeof sb; + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + if (his_state_is_will(TELOPT_XDISPLOC)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; + + memmove(nfrontp, sb, sizeof sb); + nfrontp += sizeof sb; + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + if (his_state_is_will(TELOPT_NEW_ENVIRON)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; + + memmove(nfrontp, sb, sizeof sb); + nfrontp += sizeof sb; + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { + static unsigned char sb[] = + { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; + + memmove(nfrontp, sb, sizeof sb); + nfrontp += sizeof sb; + DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); + } + if (his_state_is_will(TELOPT_TTYPE)) { + + memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); + nfrontp += sizeof ttytype_sbbuf; + DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, + sizeof ttytype_sbbuf - 2);); + } + if (his_state_is_will(TELOPT_TSPEED)) { + while (sequenceIs(tspeedsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_XDISPLOC)) { + while (sequenceIs(xdisplocsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_NEW_ENVIRON)) { + while (sequenceIs(environsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_OLD_ENVIRON)) { + while (sequenceIs(oenvironsubopt, baseline)) + ttloop(); + } + if (his_state_is_will(TELOPT_TTYPE)) { + char first[256], last[256]; + + while (sequenceIs(ttypesubopt, baseline)) + ttloop(); + + /* + * If the other side has already disabled the option, then + * we have to just go with what we (might) have already gotten. + */ + if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { + (void) strncpy(first, terminaltype, sizeof(first)); + for(;;) { + /* + * Save the unknown name, and request the next name. + */ + (void) strncpy(last, terminaltype, sizeof(last)); + _gettermname(); + if (terminaltypeok(terminaltype)) + break; + if ((strncmp(last, terminaltype, sizeof(last)) == 0) || + his_state_is_wont(TELOPT_TTYPE)) { + /* + * We've hit the end. If this is the same as + * the first name, just go with it. + */ + if (strncmp(first, terminaltype, sizeof(first)) == 0) + break; + /* + * Get the terminal name one more time, so that + * RFC1091 compliant telnets will cycle back to + * the start of the list. + */ + _gettermname(); + if (strncmp(first, terminaltype, sizeof(first)) != 0) + (void) strncpy(terminaltype, first, sizeof(first)); + break; + } + } + } + } + return(retval); +} /* end of getterminaltype */ + + void +_gettermname() +{ + /* + * If the client turned off the option, + * we can't send another request, so we + * just return. + */ + if (his_state_is_wont(TELOPT_TTYPE)) + return; + settimer(baseline); + memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); + nfrontp += sizeof ttytype_sbbuf; + DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, + sizeof ttytype_sbbuf - 2);); + while (sequenceIs(ttypesubopt, baseline)) + ttloop(); +} + + int +terminaltypeok(s) + char *s; +{ + char buf[1024]; + + if (terminaltype == NULL) + return(1); + + /* + * tgetent() will return 1 if the type is known, and + * 0 if it is not known. If it returns -1, it couldn't + * open the database. But if we can't open the database, + * it won't help to say we failed, because we won't be + * able to verify anything else. So, we treat -1 like 1. + */ + if (tgetent(buf, s) == 0) + return(0); + return(1); +} + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif /* MAXHOSTNAMELEN */ + +char *hostname; +char host_name[MAXHOSTNAMELEN]; +char remote_host_name[MAXHOSTNAMELEN]; + +#ifndef convex +extern void telnet P((int, int)); +#else +extern void telnet P((int, int, char *)); +#endif + +/* + * Get a pty, scan input lines. + */ +void +doit(who) + struct sockaddr_in *who; +{ + char *host = NULL, *inet_ntoa(); + struct hostent *hp; + int level; + int ptynum; + char user_name[256]; + + /* + * Find an available pty to use. + */ +#ifndef convex + pty = getpty(&ptynum); + if (pty < 0) + fatal(net, "All network ports in use"); +#else + for (;;) { + char *lp; + extern char *line, *getpty(); + + if ((lp = getpty()) == NULL) + fatal(net, "Out of ptys"); + + if ((pty = open(lp, O_RDWR)) >= 0) { + strncpy(line,lp, sizeof(line)-1); + line[sizeof(line)-1] = '\0'; + line[5] = 't'; + break; + } + } +#endif + +#if defined(_SC_CRAY_SECURE_SYS) + /* + * set ttyp line security label + */ + if (secflag) { + char slave_dev[16]; + + sprintf(tty_dev, "/dev/pty/%03d", ptynum); + if (setdevs(tty_dev, &dv) < 0) + fatal(net, "cannot set pty security"); + sprintf(slave_dev, "/dev/ttyp%03d", ptynum); + if (setdevs(slave_dev, &dv) < 0) + fatal(net, "cannot set tty security"); + } +#endif /* _SC_CRAY_SECURE_SYS */ + + /* get name of connected client */ + hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), + who->sin_family); + + if (hp == NULL && registerd_host_only) { + fatal(net, "Couldn't resolve your address into a host name.\r\n\ + Please contact your net administrator"); + } else if (hp && + (strlen(hp->h_name) <= (unsigned int)((utmp_len < 0) ? -utmp_len + : utmp_len))) { + host = hp->h_name; + } else { + host = inet_ntoa(who->sin_addr); + } + /* + * We must make a copy because Kerberos is probably going + * to also do a gethost* and overwrite the static data... + */ + strncpy(remote_host_name, host, sizeof(remote_host_name)-1); + remote_host_name[sizeof(remote_host_name)-1] = 0; + host = remote_host_name; + + (void) gethostname(host_name, sizeof (host_name)); + hostname = host_name; + +#if defined(AUTHENTICATION) || defined(ENCRYPTION) + auth_encrypt_init(hostname, host, "TELNETD", 1); +#endif + + init_env(); + /* + * get terminal type. + */ + *user_name = 0; + level = getterminaltype(user_name); + setenv("TERM", terminaltype ? terminaltype : "network", 1); + + /* + * Start up the login process on the slave side of the terminal + */ +#ifndef convex + startslave(host, level, user_name); + +#if defined(_SC_CRAY_SECURE_SYS) + if (secflag) { + if (setulvl(dv.dv_actlvl) < 0) + fatal(net,"cannot setulvl()"); + if (setucmp(dv.dv_actcmp) < 0) + fatal(net, "cannot setucmp()"); + } +#endif /* _SC_CRAY_SECURE_SYS */ + + telnet(net, pty); /* begin server processing */ +#else + telnet(net, pty, host); +#endif + /*NOTREACHED*/ +} /* end of doit */ + +#if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) + int +Xterm_output(ibufp, obuf, icountp, ocount) + char **ibufp, *obuf; + int *icountp, ocount; +{ + int ret; + ret = term_output(*ibufp, obuf, *icountp, ocount); + *ibufp += *icountp; + *icountp = 0; + return(ret); +} +#define term_output Xterm_output +#endif /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */ + +/* + * Main loop. Select from pty and network, and + * hand data to telnet receiver finite state machine. + */ + void +#ifndef convex +telnet(f, p) +#else +telnet(f, p, host) +#endif + int f, p; +#ifdef convex + char *host; +#endif +{ + int on = 1; +#define TABBUFSIZ 512 + char defent[TABBUFSIZ]; + char defstrs[TABBUFSIZ]; +#undef TABBUFSIZ + char *HE; + char *HN; + char *IM; + void netflush(); + int nfd; + + /* + * Initialize the slc mapping table. + */ + get_slc_defaults(); + + /* + * Do some tests where it is desireable to wait for a response. + * Rather than doing them slowly, one at a time, do them all + * at once. + */ + if (my_state_is_wont(TELOPT_SGA)) + send_will(TELOPT_SGA, 1); + /* + * Is the client side a 4.2 (NOT 4.3) system? We need to know this + * because 4.2 clients are unable to deal with TCP urgent data. + * + * To find out, we send out a "DO ECHO". If the remote system + * answers "WILL ECHO" it is probably a 4.2 client, and we note + * that fact ("WILL ECHO" ==> that the client will echo what + * WE, the server, sends it; it does NOT mean that the client will + * echo the terminal input). + */ + send_do(TELOPT_ECHO, 1); + +#ifdef LINEMODE + if (his_state_is_wont(TELOPT_LINEMODE)) { + /* Query the peer for linemode support by trying to negotiate + * the linemode option. + */ + linemode = 0; + editmode = 0; + send_do(TELOPT_LINEMODE, 1); /* send do linemode */ + } +#endif /* LINEMODE */ + + /* + * Send along a couple of other options that we wish to negotiate. + */ + send_do(TELOPT_NAWS, 1); + send_will(TELOPT_STATUS, 1); + flowmode = 1; /* default flow control state */ + restartany = -1; /* uninitialized... */ + send_do(TELOPT_LFLOW, 1); + + /* + * Spin, waiting for a response from the DO ECHO. However, + * some REALLY DUMB telnets out there might not respond + * to the DO ECHO. So, we spin looking for NAWS, (most dumb + * telnets so far seem to respond with WONT for a DO that + * they don't understand...) because by the time we get the + * response, it will already have processed the DO ECHO. + * Kludge upon kludge. + */ + while (his_will_wont_is_changing(TELOPT_NAWS)) + ttloop(); + + /* + * But... + * The client might have sent a WILL NAWS as part of its + * startup code; if so, we'll be here before we get the + * response to the DO ECHO. We'll make the assumption + * that any implementation that understands about NAWS + * is a modern enough implementation that it will respond + * to our DO ECHO request; hence we'll do another spin + * waiting for the ECHO option to settle down, which is + * what we wanted to do in the first place... + */ + if (his_want_state_is_will(TELOPT_ECHO) && + his_state_is_will(TELOPT_NAWS)) { + while (his_will_wont_is_changing(TELOPT_ECHO)) + ttloop(); + } + /* + * On the off chance that the telnet client is broken and does not + * respond to the DO ECHO we sent, (after all, we did send the + * DO NAWS negotiation after the DO ECHO, and we won't get here + * until a response to the DO NAWS comes back) simulate the + * receipt of a will echo. This will also send a WONT ECHO + * to the client, since we assume that the client failed to + * respond because it believes that it is already in DO ECHO + * mode, which we do not want. + */ + if (his_want_state_is_will(TELOPT_ECHO)) { + DIAG(TD_OPTIONS, + {sprintf(nfrontp, "td: simulating recv\r\n"); + nfrontp += strlen(nfrontp);}); + willoption(TELOPT_ECHO); + } + + /* + * Finally, to clean things up, we turn on our echo. This + * will break stupid 4.2 telnets out of local terminal echo. + */ + + if (my_state_is_wont(TELOPT_ECHO)) + send_will(TELOPT_ECHO, 1); + +#ifndef STREAMSPTY + /* + * Turn on packet mode + */ + (void) ioctl(p, TIOCPKT, (char *)&on); +#endif + +#if defined(LINEMODE) && defined(KLUDGELINEMODE) + /* + * Continuing line mode support. If client does not support + * real linemode, attempt to negotiate kludge linemode by sending + * the do timing mark sequence. + */ + if (lmodetype < REAL_LINEMODE) + send_do(TELOPT_TM, 1); +#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ + + /* + * Call telrcv() once to pick up anything received during + * terminal type negotiation, 4.2/4.3 determination, and + * linemode negotiation. + */ + telrcv(); + + (void) ioctl(f, FIONBIO, (char *)&on); + (void) ioctl(p, FIONBIO, (char *)&on); +#if defined(CRAY2) && defined(UNICOS5) + init_termdriver(f, p, interrupt, sendbrk); +#endif + +#if defined(SO_OOBINLINE) + (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, + (char *)&on, sizeof on); +#endif /* defined(SO_OOBINLINE) */ + +#ifdef SIGTSTP + (void) signal(SIGTSTP, SIG_IGN); +#endif +#ifdef SIGTTOU + /* + * Ignoring SIGTTOU keeps the kernel from blocking us + * in ttioct() in /sys/tty.c. + */ + (void) signal(SIGTTOU, SIG_IGN); +#endif + + (void) signal(SIGCHLD, cleanup); + +#if defined(CRAY2) && defined(UNICOS5) + /* + * Cray-2 will send a signal when pty modes are changed by slave + * side. Set up signal handler now. + */ + if ((int)signal(SIGUSR1, termstat) < 0) + perror("signal"); + else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) + perror("ioctl:TCSIGME"); + /* + * Make processing loop check terminal characteristics early on. + */ + termstat(); +#endif + +#ifdef TIOCNOTTY + { + register int t; + t = open(_PATH_TTY, O_RDWR); + if (t >= 0) { + (void) ioctl(t, TIOCNOTTY, (char *)0); + (void) close(t); + } + } +#endif + +#if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) + (void) setsid(); + ioctl(p, TIOCSCTTY, 0); +#endif + + /* + * Show banner that getty never gave. + * + * We put the banner in the pty input buffer. This way, it + * gets carriage return null processing, etc., just like all + * other pty --> client data. + */ + +#if !defined(CRAY) || !defined(NEWINIT) + if (getenv("USER")) + hostinfo = 0; +#endif + + if (getent(defent, "default") == 1) { + char *Getstr(); + char *cp=defstrs; + + HE = Getstr("he", &cp); + HN = Getstr("hn", &cp); + IM = Getstr("im", &cp); + if (HN && *HN) { + (void) strncpy(host_name, HN, sizeof(host_name)-1); + hostname[sizeof(host_name)-1] = '\0'; + } + if (IM == 0) + IM = ""; + } else { + IM = DEFAULT_IM; + HE = 0; + } + edithost(HE, host_name); + if (hostinfo && *IM) + putf(IM, ptyibuf2); + + if (pcc) + (void) strncat(ptyibuf2, ptyip, pcc+1); + ptyip = ptyibuf2; + pcc = strlen(ptyip); +#ifdef LINEMODE + /* + * Last check to make sure all our states are correct. + */ + init_termbuf(); + localstat(); +#endif /* LINEMODE */ + + DIAG(TD_REPORT, + {sprintf(nfrontp, "td: Entering processing loop\r\n"); + nfrontp += strlen(nfrontp);}); + +#ifdef convex + startslave(host); +#endif + + nfd = ((f > p) ? f : p) + 1; + for (;;) { + fd_set ibits, obits, xbits; + register int c; + + if (ncc < 0 && pcc < 0) + break; + +#if defined(CRAY2) && defined(UNICOS5) + if (needtermstat) + _termstat(); +#endif /* defined(CRAY2) && defined(UNICOS5) */ + FD_ZERO(&ibits); + FD_ZERO(&obits); + FD_ZERO(&xbits); + /* + * Never look for input if there's still + * stuff in the corresponding output buffer + */ + if (nfrontp - nbackp || pcc > 0) { + FD_SET(f, &obits); + } else { + FD_SET(p, &ibits); + } + if (pfrontp - pbackp || ncc > 0) { + FD_SET(p, &obits); + } else { + FD_SET(f, &ibits); + } + if (!SYNCHing) { + FD_SET(f, &xbits); + } + if ((c = select(nfd, &ibits, &obits, &xbits, + (struct timeval *)0)) < 1) { + if (c == -1) { + if (errno == EINTR) { + continue; + } + } + sleep(5); + continue; + } + + /* + * Any urgent data? + */ + if (FD_ISSET(net, &xbits)) { + SYNCHing = 1; + } + + /* + * Something to read from the network... + */ + if (FD_ISSET(net, &ibits)) { +#if !defined(SO_OOBINLINE) + /* + * In 4.2 (and 4.3 beta) systems, the + * OOB indication and data handling in the kernel + * is such that if two separate TCP Urgent requests + * come in, one byte of TCP data will be overlaid. + * This is fatal for Telnet, but we try to live + * with it. + * + * In addition, in 4.2 (and...), a special protocol + * is needed to pick up the TCP Urgent data in + * the correct sequence. + * + * What we do is: if we think we are in urgent + * mode, we look to see if we are "at the mark". + * If we are, we do an OOB receive. If we run + * this twice, we will do the OOB receive twice, + * but the second will fail, since the second + * time we were "at the mark", but there wasn't + * any data there (the kernel doesn't reset + * "at the mark" until we do a normal read). + * Once we've read the OOB data, we go ahead + * and do normal reads. + * + * There is also another problem, which is that + * since the OOB byte we read doesn't put us + * out of OOB state, and since that byte is most + * likely the TELNET DM (data mark), we would + * stay in the TELNET SYNCH (SYNCHing) state. + * So, clocks to the rescue. If we've "just" + * received a DM, then we test for the + * presence of OOB data when the receive OOB + * fails (and AFTER we did the normal mode read + * to clear "at the mark"). + */ + if (SYNCHing) { + int atmark; + + (void) ioctl(net, SIOCATMARK, (char *)&atmark); + if (atmark) { + ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); + if ((ncc == -1) && (errno == EINVAL)) { + ncc = read(net, netibuf, sizeof (netibuf)); + if (sequenceIs(didnetreceive, gotDM)) { + SYNCHing = stilloob(net); + } + } + } else { + ncc = read(net, netibuf, sizeof (netibuf)); + } + } else { + ncc = read(net, netibuf, sizeof (netibuf)); + } + settimer(didnetreceive); +#else /* !defined(SO_OOBINLINE)) */ + ncc = read(net, netibuf, sizeof (netibuf)); +#endif /* !defined(SO_OOBINLINE)) */ + if (ncc < 0 && errno == EWOULDBLOCK) + ncc = 0; + else { + if (ncc <= 0) { + break; + } + netip = netibuf; + } + DIAG((TD_REPORT | TD_NETDATA), + {sprintf(nfrontp, "td: netread %d chars\r\n", ncc); + nfrontp += strlen(nfrontp);}); + DIAG(TD_NETDATA, printdata("nd", netip, ncc)); + } + + /* + * Something to read from the pty... + */ + if (FD_ISSET(p, &ibits)) { +#ifndef STREAMSPTY + pcc = read(p, ptyibuf, BUFSIZ); +#else + pcc = readstream(p, ptyibuf, BUFSIZ); +#endif + /* + * On some systems, if we try to read something + * off the master side before the slave side is + * opened, we get EIO. + */ + if (pcc < 0 && (errno == EWOULDBLOCK || +#ifdef EAGAIN + errno == EAGAIN || +#endif + errno == EIO)) { + pcc = 0; + } else { + if (pcc <= 0) + break; +#if !defined(CRAY2) || !defined(UNICOS5) +#ifdef LINEMODE + /* + * If ioctl from pty, pass it through net + */ + if (ptyibuf[0] & TIOCPKT_IOCTL) { + copy_termbuf(ptyibuf+1, pcc-1); + localstat(); + pcc = 1; + } +#endif /* LINEMODE */ + if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { + netclear(); /* clear buffer back */ +#ifndef NO_URGENT + /* + * There are client telnets on some + * operating systems get screwed up + * royally if we send them urgent + * mode data. + */ + *nfrontp++ = IAC; + *nfrontp++ = DM; + neturg = nfrontp-1; /* off by one XXX */ + DIAG(TD_OPTIONS, + printoption("td: send IAC", DM)); + +#endif + } + if (his_state_is_will(TELOPT_LFLOW) && + (ptyibuf[0] & + (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { + int newflow = + ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; + if (newflow != flowmode) { + flowmode = newflow; + (void) sprintf(nfrontp, + "%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + flowmode ? LFLOW_ON + : LFLOW_OFF, + IAC, SE); + nfrontp += 6; + DIAG(TD_OPTIONS, printsub('>', + (unsigned char *)nfrontp-4, + 4);); + } + } + pcc--; + ptyip = ptyibuf+1; +#else /* defined(CRAY2) && defined(UNICOS5) */ + if (!uselinemode) { + unpcc = pcc; + unptyip = ptyibuf; + pcc = term_output(&unptyip, ptyibuf2, + &unpcc, BUFSIZ); + ptyip = ptyibuf2; + } else + ptyip = ptyibuf; +#endif /* defined(CRAY2) && defined(UNICOS5) */ + } + } + + while (pcc > 0) { + if ((&netobuf[BUFSIZ] - nfrontp) < 2) + break; + c = *ptyip++ & 0377, pcc--; + if (c == IAC) + *nfrontp++ = c; +#if defined(CRAY2) && defined(UNICOS5) + else if (c == '\n' && + my_state_is_wont(TELOPT_BINARY) && newmap) + *nfrontp++ = '\r'; +#endif /* defined(CRAY2) && defined(UNICOS5) */ + *nfrontp++ = c; + if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { + if (pcc > 0 && ((*ptyip & 0377) == '\n')) { + *nfrontp++ = *ptyip++ & 0377; + pcc--; + } else + *nfrontp++ = '\0'; + } + } +#if defined(CRAY2) && defined(UNICOS5) + /* + * If chars were left over from the terminal driver, + * note their existence. + */ + if (!uselinemode && unpcc) { + pcc = unpcc; + unpcc = 0; + ptyip = unptyip; + } +#endif /* defined(CRAY2) && defined(UNICOS5) */ + + if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) + netflush(); + if (ncc > 0) + telrcv(); + if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) + ptyflush(); + } + cleanup(0); +} /* end of telnet */ + +#ifndef TCSIG +# ifdef TIOCSIG +# define TCSIG TIOCSIG +# endif +#endif + +#ifdef STREAMSPTY + +int flowison = -1; /* current state of flow: -1 is unknown */ + +int readstream(p, ibuf, bufsize) + int p; + char *ibuf; + int bufsize; +{ + int flags = 0; + int ret = 0; + struct termios *tsp; + struct termio *tp; + struct iocblk *ip; + char vstop, vstart; + int ixon; + int newflow; + + strbufc.maxlen = BUFSIZ; + strbufc.buf = (char *)ctlbuf; + strbufd.maxlen = bufsize-1; + strbufd.len = 0; + strbufd.buf = ibuf+1; + ibuf[0] = 0; + + ret = getmsg(p, &strbufc, &strbufd, &flags); + if (ret < 0) /* error of some sort -- probably EAGAIN */ + return(-1); + + if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { + /* data message */ + if (strbufd.len > 0) { /* real data */ + return(strbufd.len + 1); /* count header char */ + } else { + /* nothing there */ + errno = EAGAIN; + return(-1); + } + } + + /* + * It's a control message. Return 1, to look at the flag we set + */ + + switch (ctlbuf[0]) { + case M_FLUSH: + if (ibuf[1] & FLUSHW) + ibuf[0] = TIOCPKT_FLUSHWRITE; + return(1); + + case M_IOCTL: + ip = (struct iocblk *) (ibuf+1); + + switch (ip->ioc_cmd) { + case TCSETS: + case TCSETSW: + case TCSETSF: + tsp = (struct termios *) + (ibuf+1 + sizeof(struct iocblk)); + vstop = tsp->c_cc[VSTOP]; + vstart = tsp->c_cc[VSTART]; + ixon = tsp->c_iflag & IXON; + break; + case TCSETA: + case TCSETAW: + case TCSETAF: + tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); + vstop = tp->c_cc[VSTOP]; + vstart = tp->c_cc[VSTART]; + ixon = tp->c_iflag & IXON; + break; + default: + errno = EAGAIN; + return(-1); + } + + newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; + if (newflow != flowison) { /* it's a change */ + flowison = newflow; + ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; + return(1); + } + } + + /* nothing worth doing anything about */ + errno = EAGAIN; + return(-1); +} +#endif /* STREAMSPTY */ + +/* + * Send interrupt to process on other side of pty. + * If it is in raw mode, just write NULL; + * otherwise, write intr char. + */ + void +interrupt() +{ + ptyflush(); /* half-hearted */ + +#if defined(STREAMSPTY) && defined(TIOCSIGNAL) + /* Streams PTY style ioctl to post a signal */ + { + int sig = SIGINT; + (void) ioctl(pty, TIOCSIGNAL, &sig); + (void) ioctl(pty, I_FLUSH, FLUSHR); + } +#else +#ifdef TCSIG + (void) ioctl(pty, TCSIG, (char *)SIGINT); +#else /* TCSIG */ + init_termbuf(); + *pfrontp++ = slctab[SLC_IP].sptr ? + (unsigned char)*slctab[SLC_IP].sptr : '\177'; +#endif /* TCSIG */ +#endif +} + +/* + * Send quit to process on other side of pty. + * If it is in raw mode, just write NULL; + * otherwise, write quit char. + */ + void +sendbrk() +{ + ptyflush(); /* half-hearted */ +#ifdef TCSIG + (void) ioctl(pty, TCSIG, (char *)SIGQUIT); +#else /* TCSIG */ + init_termbuf(); + *pfrontp++ = slctab[SLC_ABORT].sptr ? + (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; +#endif /* TCSIG */ +} + + void +sendsusp() +{ +#ifdef SIGTSTP + ptyflush(); /* half-hearted */ +# ifdef TCSIG + (void) ioctl(pty, TCSIG, (char *)SIGTSTP); +# else /* TCSIG */ + *pfrontp++ = slctab[SLC_SUSP].sptr ? + (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; +# endif /* TCSIG */ +#endif /* SIGTSTP */ +} + +/* + * When we get an AYT, if ^T is enabled, use that. Otherwise, + * just send back "[Yes]". + */ + void +recv_ayt() +{ +#if defined(SIGINFO) && defined(TCSIG) + if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { + (void) ioctl(pty, TCSIG, (char *)SIGINFO); + return; + } +#endif + (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); + nfrontp += 9; +} + + void +doeof() +{ + init_termbuf(); + +#if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) + if (!tty_isediting()) { + extern char oldeofc; + *pfrontp++ = oldeofc; + return; + } +#endif + *pfrontp++ = slctab[SLC_EOF].sptr ? + (unsigned char)*slctab[SLC_EOF].sptr : '\004'; +} diff --git a/telnetd.tproj/telnetd.h b/telnetd.tproj/telnetd.h new file mode 100644 index 0000000..56ccdcd --- /dev/null +++ b/telnetd.tproj/telnetd.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)telnetd.h 8.1 (Berkeley) 6/4/93 + */ + + +#include "defs.h" +#include "ext.h" +#include + +#ifdef DIAGNOSTICS +#define DIAG(a,b) if (diagnostic & (a)) b +#else +#define DIAG(a,b) +#endif + +/* other external variables */ +extern char **environ; +extern int errno; + diff --git a/telnetd.tproj/termstat.c b/telnetd.tproj/termstat.c new file mode 100644 index 0000000..0705dec --- /dev/null +++ b/telnetd.tproj/termstat.c @@ -0,0 +1,683 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#include "telnetd.h" + +/* + * local variables + */ +int def_tspeed = -1, def_rspeed = -1; +#ifdef TIOCSWINSZ +int def_row = 0, def_col = 0; +#endif +#ifdef LINEMODE +static int _terminit = 0; +#endif /* LINEMODE */ + +#if defined(CRAY2) && defined(UNICOS5) +int newmap = 1; /* nonzero if \n maps to ^M^J */ +#endif + +#ifdef LINEMODE +/* + * localstat + * + * This function handles all management of linemode. + * + * Linemode allows the client to do the local editing of data + * and send only complete lines to the server. Linemode state is + * based on the state of the pty driver. If the pty is set for + * external processing, then we can use linemode. Further, if we + * can use real linemode, then we can look at the edit control bits + * in the pty to determine what editing the client should do. + * + * Linemode support uses the following state flags to keep track of + * current and desired linemode state. + * alwayslinemode : true if -l was specified on the telnetd + * command line. It means to have linemode on as much as + * possible. + * + * lmodetype: signifies whether the client can + * handle real linemode, or if use of kludgeomatic linemode + * is preferred. It will be set to one of the following: + * REAL_LINEMODE : use linemode option + * NO_KLUDGE : don't initiate kludge linemode. + * KLUDGE_LINEMODE : use kludge linemode + * NO_LINEMODE : client is ignorant of linemode + * + * linemode, uselinemode : linemode is true if linemode + * is currently on, uselinemode is the state that we wish + * to be in. If another function wishes to turn linemode + * on or off, it sets or clears uselinemode. + * + * editmode, useeditmode : like linemode/uselinemode, but + * these contain the edit mode states (edit and trapsig). + * + * The state variables correspond to some of the state information + * in the pty. + * linemode: + * In real linemode, this corresponds to whether the pty + * expects external processing of incoming data. + * In kludge linemode, this more closely corresponds to the + * whether normal processing is on or not. (ICANON in + * system V, or COOKED mode in BSD.) + * If the -l option was specified (alwayslinemode), then + * an attempt is made to force external processing on at + * all times. + * + * The following heuristics are applied to determine linemode + * handling within the server. + * 1) Early on in starting up the server, an attempt is made + * to negotiate the linemode option. If this succeeds + * then lmodetype is set to REAL_LINEMODE and all linemode + * processing occurs in the context of the linemode option. + * 2) If the attempt to negotiate the linemode option failed, + * and the "-k" (don't initiate kludge linemode) isn't set, + * then we try to use kludge linemode. We test for this + * capability by sending "do Timing Mark". If a positive + * response comes back, then we assume that the client + * understands kludge linemode (ech!) and the + * lmodetype flag is set to KLUDGE_LINEMODE. + * 3) Otherwise, linemode is not supported at all and + * lmodetype remains set to NO_LINEMODE (which happens + * to be 0 for convenience). + * 4) At any time a command arrives that implies a higher + * state of linemode support in the client, we move to that + * linemode support. + * + * A short explanation of kludge linemode is in order here. + * 1) The heuristic to determine support for kludge linemode + * is to send a do timing mark. We assume that a client + * that supports timing marks also supports kludge linemode. + * A risky proposition at best. + * 2) Further negotiation of linemode is done by changing the + * the server's state regarding SGA. If server will SGA, + * then linemode is off, if server won't SGA, then linemode + * is on. + */ + void +localstat() +{ + void netflush(); + int need_will_echo = 0; + +#if defined(CRAY2) && defined(UNICOS5) + /* + * Keep track of that ol' CR/NL mapping while we're in the + * neighborhood. + */ + newmap = tty_isnewmap(); +#endif /* defined(CRAY2) && defined(UNICOS5) */ + + /* + * Check for state of BINARY options. + */ + if (tty_isbinaryin()) { + if (his_want_state_is_wont(TELOPT_BINARY)) + send_do(TELOPT_BINARY, 1); + } else { + if (his_want_state_is_will(TELOPT_BINARY)) + send_dont(TELOPT_BINARY, 1); + } + + if (tty_isbinaryout()) { + if (my_want_state_is_wont(TELOPT_BINARY)) + send_will(TELOPT_BINARY, 1); + } else { + if (my_want_state_is_will(TELOPT_BINARY)) + send_wont(TELOPT_BINARY, 1); + } + + /* + * Check for changes to flow control if client supports it. + */ + flowstat(); + + /* + * Check linemode on/off state + */ + uselinemode = tty_linemode(); + + /* + * If alwayslinemode is on, and pty is changing to turn it off, then + * force linemode back on. + */ + if (alwayslinemode && linemode && !uselinemode) { + uselinemode = 1; + tty_setlinemode(uselinemode); + } + +#ifdef ENCRYPTION + /* + * If the terminal is not echoing, but editing is enabled, + * something like password input is going to happen, so + * if we the other side is not currently sending encrypted + * data, ask the other side to start encrypting. + */ + if (his_state_is_will(TELOPT_ENCRYPT)) { + static int enc_passwd = 0; + if (uselinemode && !tty_isecho() && tty_isediting() + && (enc_passwd == 0) && !decrypt_input) { + encrypt_send_request_start(); + enc_passwd = 1; + } else if (enc_passwd) { + encrypt_send_request_end(); + enc_passwd = 0; + } + } +#endif /* ENCRYPTION */ + + /* + * Do echo mode handling as soon as we know what the + * linemode is going to be. + * If the pty has echo turned off, then tell the client that + * the server will echo. If echo is on, then the server + * will echo if in character mode, but in linemode the + * client should do local echoing. The state machine will + * not send anything if it is unnecessary, so don't worry + * about that here. + * + * If we need to send the WILL ECHO (because echo is off), + * then delay that until after we have changed the MODE. + * This way, when the user is turning off both editing + * and echo, the client will get editing turned off first. + * This keeps the client from going into encryption mode + * and then right back out if it is doing auto-encryption + * when passwords are being typed. + */ + if (uselinemode) { + if (tty_isecho()) + send_wont(TELOPT_ECHO, 1); + else + need_will_echo = 1; +#ifdef KLUDGELINEMODE + if (lmodetype == KLUDGE_OK) + lmodetype = KLUDGE_LINEMODE; +#endif + } + + /* + * If linemode is being turned off, send appropriate + * command and then we're all done. + */ + if (!uselinemode && linemode) { +# ifdef KLUDGELINEMODE + if (lmodetype == REAL_LINEMODE) { +# endif /* KLUDGELINEMODE */ + send_dont(TELOPT_LINEMODE, 1); +# ifdef KLUDGELINEMODE + } else if (lmodetype == KLUDGE_LINEMODE) + send_will(TELOPT_SGA, 1); +# endif /* KLUDGELINEMODE */ + send_will(TELOPT_ECHO, 1); + linemode = uselinemode; + goto done; + } + +# ifdef KLUDGELINEMODE + /* + * If using real linemode check edit modes for possible later use. + * If we are in kludge linemode, do the SGA negotiation. + */ + if (lmodetype == REAL_LINEMODE) { +# endif /* KLUDGELINEMODE */ + useeditmode = 0; + if (tty_isediting()) + useeditmode |= MODE_EDIT; + if (tty_istrapsig()) + useeditmode |= MODE_TRAPSIG; + if (tty_issofttab()) + useeditmode |= MODE_SOFT_TAB; + if (tty_islitecho()) + useeditmode |= MODE_LIT_ECHO; +# ifdef KLUDGELINEMODE + } else if (lmodetype == KLUDGE_LINEMODE) { + if (tty_isediting() && uselinemode) + send_wont(TELOPT_SGA, 1); + else + send_will(TELOPT_SGA, 1); + } +# endif /* KLUDGELINEMODE */ + + /* + * Negotiate linemode on if pty state has changed to turn it on. + * Send appropriate command and send along edit mode, then all done. + */ + if (uselinemode && !linemode) { +# ifdef KLUDGELINEMODE + if (lmodetype == KLUDGE_LINEMODE) { + send_wont(TELOPT_SGA, 1); + } else if (lmodetype == REAL_LINEMODE) { +# endif /* KLUDGELINEMODE */ + send_do(TELOPT_LINEMODE, 1); + /* send along edit modes */ + (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB, + TELOPT_LINEMODE, LM_MODE, useeditmode, + IAC, SE); + nfrontp += 7; + editmode = useeditmode; +# ifdef KLUDGELINEMODE + } +# endif /* KLUDGELINEMODE */ + linemode = uselinemode; + goto done; + } + +# ifdef KLUDGELINEMODE + /* + * None of what follows is of any value if not using + * real linemode. + */ + if (lmodetype < REAL_LINEMODE) + goto done; +# endif /* KLUDGELINEMODE */ + + if (linemode && his_state_is_will(TELOPT_LINEMODE)) { + /* + * If edit mode changed, send edit mode. + */ + if (useeditmode != editmode) { + /* + * Send along appropriate edit mode mask. + */ + (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB, + TELOPT_LINEMODE, LM_MODE, useeditmode, + IAC, SE); + nfrontp += 7; + editmode = useeditmode; + } + + + /* + * Check for changes to special characters in use. + */ + start_slc(0); + check_slc(); + (void) end_slc(0); + } + +done: + if (need_will_echo) + send_will(TELOPT_ECHO, 1); + /* + * Some things should be deferred until after the pty state has + * been set by the local process. Do those things that have been + * deferred now. This only happens once. + */ + if (_terminit == 0) { + _terminit = 1; + defer_terminit(); + } + + netflush(); + set_termbuf(); + return; + +} /* end of localstat */ +#endif /* LINEMODE */ + +/* + * flowstat + * + * Check for changes to flow control + */ + void +flowstat() +{ + if (his_state_is_will(TELOPT_LFLOW)) { + if (tty_flowmode() != flowmode) { + flowmode = tty_flowmode(); + (void) sprintf(nfrontp, "%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + flowmode ? LFLOW_ON : LFLOW_OFF, + IAC, SE); + nfrontp += 6; + } + if (tty_restartany() != restartany) { + restartany = tty_restartany(); + (void) sprintf(nfrontp, "%c%c%c%c%c%c", + IAC, SB, TELOPT_LFLOW, + restartany ? LFLOW_RESTART_ANY + : LFLOW_RESTART_XON, + IAC, SE); + nfrontp += 6; + } + } +} + +/* + * clientstat + * + * Process linemode related requests from the client. + * Client can request a change to only one of linemode, editmode or slc's + * at a time, and if using kludge linemode, then only linemode may be + * affected. + */ + void +clientstat(code, parm1, parm2) + register int code, parm1, parm2; +{ + void netflush(); + + /* + * Get a copy of terminal characteristics. + */ + init_termbuf(); + + /* + * Process request from client. code tells what it is. + */ + switch (code) { +#ifdef LINEMODE + case TELOPT_LINEMODE: + /* + * Don't do anything unless client is asking us to change + * modes. + */ + uselinemode = (parm1 == WILL); + if (uselinemode != linemode) { +# ifdef KLUDGELINEMODE + /* + * If using kludge linemode, make sure that + * we can do what the client asks. + * We can not turn off linemode if alwayslinemode + * and the ICANON bit is set. + */ + if (lmodetype == KLUDGE_LINEMODE) { + if (alwayslinemode && tty_isediting()) { + uselinemode = 1; + } + } + + /* + * Quit now if we can't do it. + */ + if (uselinemode == linemode) + return; + + /* + * If using real linemode and linemode is being + * turned on, send along the edit mode mask. + */ + if (lmodetype == REAL_LINEMODE && uselinemode) +# else /* KLUDGELINEMODE */ + if (uselinemode) +# endif /* KLUDGELINEMODE */ + { + useeditmode = 0; + if (tty_isediting()) + useeditmode |= MODE_EDIT; + if (tty_istrapsig) + useeditmode |= MODE_TRAPSIG; + if (tty_issofttab()) + useeditmode |= MODE_SOFT_TAB; + if (tty_islitecho()) + useeditmode |= MODE_LIT_ECHO; + (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, + SB, TELOPT_LINEMODE, LM_MODE, + useeditmode, IAC, SE); + nfrontp += 7; + editmode = useeditmode; + } + + + tty_setlinemode(uselinemode); + + linemode = uselinemode; + + if (!linemode) + send_will(TELOPT_ECHO, 1); + } + break; + + case LM_MODE: + { + register int ack, changed; + + /* + * Client has sent along a mode mask. If it agrees with + * what we are currently doing, ignore it; if not, it could + * be viewed as a request to change. Note that the server + * will change to the modes in an ack if it is different from + * what we currently have, but we will not ack the ack. + */ + useeditmode &= MODE_MASK; + ack = (useeditmode & MODE_ACK); + useeditmode &= ~MODE_ACK; + + if (changed = (useeditmode ^ editmode)) { + /* + * This check is for a timing problem. If the + * state of the tty has changed (due to the user + * application) we need to process that info + * before we write in the state contained in the + * ack!!! This gets out the new MODE request, + * and when the ack to that command comes back + * we'll set it and be in the right mode. + */ + if (ack) + localstat(); + if (changed & MODE_EDIT) + tty_setedit(useeditmode & MODE_EDIT); + + if (changed & MODE_TRAPSIG) + tty_setsig(useeditmode & MODE_TRAPSIG); + + if (changed & MODE_SOFT_TAB) + tty_setsofttab(useeditmode & MODE_SOFT_TAB); + + if (changed & MODE_LIT_ECHO) + tty_setlitecho(useeditmode & MODE_LIT_ECHO); + + set_termbuf(); + + if (!ack) { + (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, + SB, TELOPT_LINEMODE, LM_MODE, + useeditmode|MODE_ACK, + IAC, SE); + nfrontp += 7; + } + + editmode = useeditmode; + } + + break; + + } /* end of case LM_MODE */ +#endif /* LINEMODE */ + + case TELOPT_NAWS: +#ifdef TIOCSWINSZ + { + struct winsize ws; + + def_col = parm1; + def_row = parm2; +#ifdef LINEMODE + /* + * Defer changing window size until after terminal is + * initialized. + */ + if (terminit() == 0) + return; +#endif /* LINEMODE */ + + /* + * Change window size as requested by client. + */ + + ws.ws_col = parm1; + ws.ws_row = parm2; + (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); + } +#endif /* TIOCSWINSZ */ + + break; + + case TELOPT_TSPEED: + { + def_tspeed = parm1; + def_rspeed = parm2; +#ifdef LINEMODE + /* + * Defer changing the terminal speed. + */ + if (terminit() == 0) + return; +#endif /* LINEMODE */ + /* + * Change terminal speed as requested by client. + * We set the receive speed first, so that if we can't + * store seperate receive and transmit speeds, the transmit + * speed will take precedence. + */ + tty_rspeed(parm2); + tty_tspeed(parm1); + set_termbuf(); + + break; + + } /* end of case TELOPT_TSPEED */ + + default: + /* What? */ + break; + } /* end of switch */ + +#if defined(CRAY2) && defined(UNICOS5) + /* + * Just in case of the likely event that we changed the pty state. + */ + rcv_ioctl(); +#endif /* defined(CRAY2) && defined(UNICOS5) */ + + netflush(); + +} /* end of clientstat */ + +#if defined(CRAY2) && defined(UNICOS5) + void +termstat() +{ + needtermstat = 1; +} + + void +_termstat() +{ + needtermstat = 0; + init_termbuf(); + localstat(); + rcv_ioctl(); +} +#endif /* defined(CRAY2) && defined(UNICOS5) */ + +#ifdef LINEMODE +/* + * defer_terminit + * + * Some things should not be done until after the login process has started + * and all the pty modes are set to what they are supposed to be. This + * function is called when the pty state has been processed for the first time. + * It calls other functions that do things that were deferred in each module. + */ + void +defer_terminit() +{ + + /* + * local stuff that got deferred. + */ + if (def_tspeed != -1) { + clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed); + def_tspeed = def_rspeed = 0; + } + +#ifdef TIOCSWINSZ + if (def_col || def_row) { + struct winsize ws; + + memset((char *)&ws, 0, sizeof(ws)); + ws.ws_col = def_col; + ws.ws_row = def_row; + (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); + } +#endif + + /* + * The only other module that currently defers anything. + */ + deferslc(); + +} /* end of defer_terminit */ + +/* + * terminit + * + * Returns true if the pty state has been processed yet. + */ + int +terminit() +{ + return(_terminit); + +} /* end of terminit */ +#endif /* LINEMODE */ diff --git a/telnetd.tproj/utility.c b/telnetd.tproj/utility.c new file mode 100644 index 0000000..9154811 --- /dev/null +++ b/telnetd.tproj/utility.c @@ -0,0 +1,1215 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95"; +#endif /* not lint */ + +#define PRINTOPTIONS +#include "telnetd.h" + +/* + * utility functions performing io related tasks + */ + +/* + * ttloop + * + * A small subroutine to flush the network output buffer, get some data + * from the network, and pass it through the telnet state machine. We + * also flush the pty input buffer (by dropping its data) if it becomes + * too full. + */ + + void +ttloop() +{ + void netflush(); + + DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n"); + nfrontp += strlen(nfrontp);}); + if (nfrontp-nbackp) { + netflush(); + } + ncc = read(net, netibuf, sizeof netibuf); + if (ncc < 0) { + syslog(LOG_INFO, "ttloop: read: %m\n"); + exit(1); + } else if (ncc == 0) { + syslog(LOG_INFO, "ttloop: peer died: %m\n"); + exit(1); + } + DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); + nfrontp += strlen(nfrontp);}); + netip = netibuf; + telrcv(); /* state machine */ + if (ncc > 0) { + pfrontp = pbackp = ptyobuf; + telrcv(); + } +} /* end of ttloop */ + +/* + * Check a descriptor to see if out of band data exists on it. + */ + int +stilloob(s) + int s; /* socket number */ +{ + static struct timeval timeout = { 0 }; + fd_set excepts; + int value; + + do { + FD_ZERO(&excepts); + FD_SET(s, &excepts); + value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); + } while ((value == -1) && (errno == EINTR)); + + if (value < 0) { + fatalperror(pty, "select"); + } + if (FD_ISSET(s, &excepts)) { + return 1; + } else { + return 0; + } +} + + void +ptyflush() +{ + int n; + + if ((n = pfrontp - pbackp) > 0) { + DIAG((TD_REPORT | TD_PTYDATA), + { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); + nfrontp += strlen(nfrontp); }); + DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); + n = write(pty, pbackp, n); + } + if (n < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) + return; + cleanup(0); + } + pbackp += n; + if (pbackp == pfrontp) + pbackp = pfrontp = ptyobuf; +} + +/* + * nextitem() + * + * Return the address of the next "item" in the TELNET data + * stream. This will be the address of the next character if + * the current address is a user data character, or it will + * be the address of the character following the TELNET command + * if the current address is a TELNET IAC ("I Am a Command") + * character. + */ + char * +nextitem(current) + char *current; +{ + if ((*current&0xff) != IAC) { + return current+1; + } + switch (*(current+1)&0xff) { + case DO: + case DONT: + case WILL: + case WONT: + return current+3; + case SB: /* loop forever looking for the SE */ + { + register char *look = current+2; + + for (;;) { + if ((*look++&0xff) == IAC) { + if ((*look++&0xff) == SE) { + return look; + } + } + } + } + default: + return current+2; + } +} /* end of nextitem */ + + +/* + * netclear() + * + * We are about to do a TELNET SYNCH operation. Clear + * the path to the network. + * + * Things are a bit tricky since we may have sent the first + * byte or so of a previous TELNET command into the network. + * So, we have to scan the network buffer from the beginning + * until we are up to where we want to be. + * + * A side effect of what we do, just to keep things + * simple, is to clear the urgent data pointer. The principal + * caller should be setting the urgent data pointer AFTER calling + * us in any case. + */ + void +netclear() +{ + register char *thisitem, *next; + char *good; +#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ + ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) + +#ifdef ENCRYPTION + thisitem = nclearto > netobuf ? nclearto : netobuf; +#else /* ENCRYPTION */ + thisitem = netobuf; +#endif /* ENCRYPTION */ + + while ((next = nextitem(thisitem)) <= nbackp) { + thisitem = next; + } + + /* Now, thisitem is first before/at boundary. */ + +#ifdef ENCRYPTION + good = nclearto > netobuf ? nclearto : netobuf; +#else /* ENCRYPTION */ + good = netobuf; /* where the good bytes go */ +#endif /* ENCRYPTION */ + + while (nfrontp > thisitem) { + if (wewant(thisitem)) { + int length; + + next = thisitem; + do { + next = nextitem(next); + } while (wewant(next) && (nfrontp > next)); + length = next-thisitem; + memmove(good, thisitem, length); + good += length; + thisitem = next; + } else { + thisitem = nextitem(thisitem); + } + } + + nbackp = netobuf; + nfrontp = good; /* next byte to be sent */ + neturg = 0; +} /* end of netclear */ + +/* + * netflush + * Send as much data as possible to the network, + * handling requests for urgent data. + */ + void +netflush() +{ + int n; + extern int not42; + + if ((n = nfrontp - nbackp) > 0) { + DIAG(TD_REPORT, + { sprintf(nfrontp, "td: netflush %d chars\r\n", n); + n += strlen(nfrontp); /* get count first */ + nfrontp += strlen(nfrontp); /* then move pointer */ + }); +#ifdef ENCRYPTION + if (encrypt_output) { + char *s = nclearto ? nclearto : nbackp; + if (nfrontp - s > 0) { + (*encrypt_output)((unsigned char *)s, nfrontp-s); + nclearto = nfrontp; + } + } +#endif /* ENCRYPTION */ + /* + * if no urgent data, or if the other side appears to be an + * old 4.2 client (and thus unable to survive TCP urgent data), + * write the entire buffer in non-OOB mode. + */ + if ((neturg == 0) || (not42 == 0)) { + n = write(net, nbackp, n); /* normal write */ + } else { + n = neturg - nbackp; + /* + * In 4.2 (and 4.3) systems, there is some question about + * what byte in a sendOOB operation is the "OOB" data. + * To make ourselves compatible, we only send ONE byte + * out of band, the one WE THINK should be OOB (though + * we really have more the TCP philosophy of urgent data + * rather than the Unix philosophy of OOB data). + */ + if (n > 1) { + n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ + } else { + n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ + } + } + } + if (n < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) + return; + cleanup(0); + } + nbackp += n; +#ifdef ENCRYPTION + if (nbackp > nclearto) + nclearto = 0; +#endif /* ENCRYPTION */ + if (nbackp >= neturg) { + neturg = 0; + } + if (nbackp == nfrontp) { + nbackp = nfrontp = netobuf; +#ifdef ENCRYPTION + nclearto = 0; +#endif /* ENCRYPTION */ + } + return; +} /* end of netflush */ + + +/* + * writenet + * + * Just a handy little function to write a bit of raw data to the net. + * It will force a transmit of the buffer if necessary + * + * arguments + * ptr - A pointer to a character string to write + * len - How many bytes to write + */ + void +writenet(ptr, len) + register unsigned char *ptr; + register int len; +{ + /* flush buffer if no room for new data) */ + if ((&netobuf[BUFSIZ] - nfrontp) < len) { + /* if this fails, don't worry, buffer is a little big */ + netflush(); + } + + memmove(nfrontp, ptr, len); + nfrontp += len; + +} /* end of writenet */ + + +/* + * miscellaneous functions doing a variety of little jobs follow ... + */ + + + void +fatal(f, msg) + int f; + char *msg; +{ + char buf[BUFSIZ]; + + (void) sprintf(buf, "telnetd: %s.\r\n", msg); +#ifdef ENCRYPTION + if (encrypt_output) { + /* + * Better turn off encryption first.... + * Hope it flushes... + */ + encrypt_send_end(); + netflush(); + } +#endif /* ENCRYPTION */ + (void) write(f, buf, (int)strlen(buf)); + sleep(1); /*XXX*/ + exit(1); +} + + void +fatalperror(f, msg) + int f; + char *msg; +{ + char buf[BUFSIZ], *strerror(); + + (void) sprintf(buf, "%s: %s", msg, strerror(errno)); + fatal(f, buf); +} + +char editedhost[32]; + + void +edithost(pat, host) + register char *pat; + register char *host; +{ + register char *res = editedhost; + char *strncpy(); + + if (!pat) + pat = ""; + while (*pat) { + switch (*pat) { + + case '#': + if (*host) + host++; + break; + + case '@': + if (*host) + *res++ = *host++; + break; + + default: + *res++ = *pat; + break; + } + if (res == &editedhost[sizeof editedhost - 1]) { + *res = '\0'; + return; + } + pat++; + } + if (*host) + (void) strncpy(res, host, + sizeof editedhost - (res - editedhost) -1); + else + *res = '\0'; + editedhost[sizeof editedhost - 1] = '\0'; +} + +static char *putlocation; + + void +putstr(s) + register char *s; +{ + + while (*s) + putchr(*s++); +} + + void +putchr(cc) + int cc; +{ + *putlocation++ = cc; +} + +/* + * This is split on two lines so that SCCS will not see the M + * between two % signs and expand it... + */ +static char fmtstr[] = { "%l:%M\ +%P on %A, %d %B %Y" }; + + void +putf(cp, where) + register char *cp; + char *where; +{ + char *slash; + time_t t; + char db[100]; +#ifdef STREAMSPTY + extern char *strchr(); +#else + extern char *strrchr(); +#endif + + putlocation = where; + + while (*cp) { + if (*cp != '%') { + putchr(*cp++); + continue; + } + switch (*++cp) { + + case 't': +#ifdef STREAMSPTY + /* names are like /dev/pts/2 -- we want pts/2 */ + slash = strchr(line+1, '/'); +#else + slash = strrchr(line, '/'); +#endif + if (slash == (char *) 0) + putstr(line); + else + putstr(&slash[1]); + break; + + case 'h': + putstr(editedhost); + break; + + case 'd': + (void)time(&t); + (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); + putstr(db); + break; + + case '%': + putchr('%'); + break; + } + cp++; + } +} + +#ifdef DIAGNOSTICS +/* + * Print telnet options and commands in plain text, if possible. + */ + void +printoption(fmt, option) + register char *fmt; + register int option; +{ + if (TELOPT_OK(option)) + sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); + else if (TELCMD_OK(option)) + sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option)); + else + sprintf(nfrontp, "%s %d\r\n", fmt, option); + nfrontp += strlen(nfrontp); + return; +} + + void +printsub(direction, pointer, length) + char direction; /* '<' or '>' */ + unsigned char *pointer; /* where suboption data sits */ + int length; /* length of suboption data */ +{ + register int i; + char buf[512]; + + if (!(diagnostic & TD_OPTIONS)) + return; + + if (direction) { + sprintf(nfrontp, "td: %s suboption ", + direction == '<' ? "recv" : "send"); + nfrontp += strlen(nfrontp); + if (length >= 3) { + register int j; + + i = pointer[length-2]; + j = pointer[length-1]; + + if (i != IAC || j != SE) { + sprintf(nfrontp, "(terminated by "); + nfrontp += strlen(nfrontp); + if (TELOPT_OK(i)) + sprintf(nfrontp, "%s ", TELOPT(i)); + else if (TELCMD_OK(i)) + sprintf(nfrontp, "%s ", TELCMD(i)); + else + sprintf(nfrontp, "%d ", i); + nfrontp += strlen(nfrontp); + if (TELOPT_OK(j)) + sprintf(nfrontp, "%s", TELOPT(j)); + else if (TELCMD_OK(j)) + sprintf(nfrontp, "%s", TELCMD(j)); + else + sprintf(nfrontp, "%d", j); + nfrontp += strlen(nfrontp); + sprintf(nfrontp, ", not IAC SE!) "); + nfrontp += strlen(nfrontp); + } + } + length -= 2; + } + if (length < 1) { + sprintf(nfrontp, "(Empty suboption??\?)"); + nfrontp += strlen(nfrontp); + return; + } + switch (pointer[0]) { + case TELOPT_TTYPE: + sprintf(nfrontp, "TERMINAL-TYPE "); + nfrontp += strlen(nfrontp); + switch (pointer[1]) { + case TELQUAL_IS: + sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); + break; + case TELQUAL_SEND: + sprintf(nfrontp, "SEND"); + break; + default: + sprintf(nfrontp, + "- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + nfrontp += strlen(nfrontp); + break; + case TELOPT_TSPEED: + sprintf(nfrontp, "TERMINAL-SPEED"); + nfrontp += strlen(nfrontp); + if (length < 2) { + sprintf(nfrontp, " (empty suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case TELQUAL_IS: + sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2); + nfrontp += strlen(nfrontp); + break; + default: + if (pointer[1] == 1) + sprintf(nfrontp, " SEND"); + else + sprintf(nfrontp, " %d (unknown)", pointer[1]); + nfrontp += strlen(nfrontp); + for (i = 2; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + break; + + case TELOPT_LFLOW: + sprintf(nfrontp, "TOGGLE-FLOW-CONTROL"); + nfrontp += strlen(nfrontp); + if (length < 2) { + sprintf(nfrontp, " (empty suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case LFLOW_OFF: + sprintf(nfrontp, " OFF"); break; + case LFLOW_ON: + sprintf(nfrontp, " ON"); break; + case LFLOW_RESTART_ANY: + sprintf(nfrontp, " RESTART-ANY"); break; + case LFLOW_RESTART_XON: + sprintf(nfrontp, " RESTART-XON"); break; + default: + sprintf(nfrontp, " %d (unknown)", pointer[1]); + } + nfrontp += strlen(nfrontp); + for (i = 2; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + + case TELOPT_NAWS: + sprintf(nfrontp, "NAWS"); + nfrontp += strlen(nfrontp); + if (length < 2) { + sprintf(nfrontp, " (empty suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + if (length == 2) { + sprintf(nfrontp, " ?%d?", pointer[1]); + nfrontp += strlen(nfrontp); + break; + } + sprintf(nfrontp, " %d %d (%d)", + pointer[1], pointer[2], + (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); + nfrontp += strlen(nfrontp); + if (length == 4) { + sprintf(nfrontp, " ?%d?", pointer[3]); + nfrontp += strlen(nfrontp); + break; + } + sprintf(nfrontp, " %d %d (%d)", + pointer[3], pointer[4], + (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); + nfrontp += strlen(nfrontp); + for (i = 5; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + + case TELOPT_LINEMODE: + sprintf(nfrontp, "LINEMODE "); + nfrontp += strlen(nfrontp); + if (length < 2) { + sprintf(nfrontp, " (empty suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case WILL: + sprintf(nfrontp, "WILL "); + goto common; + case WONT: + sprintf(nfrontp, "WONT "); + goto common; + case DO: + sprintf(nfrontp, "DO "); + goto common; + case DONT: + sprintf(nfrontp, "DONT "); + common: + nfrontp += strlen(nfrontp); + if (length < 3) { + sprintf(nfrontp, "(no option??\?)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[2]) { + case LM_FORWARDMASK: + sprintf(nfrontp, "Forward Mask"); + nfrontp += strlen(nfrontp); + for (i = 3; i < length; i++) { + sprintf(nfrontp, " %x", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + default: + sprintf(nfrontp, "%d (unknown)", pointer[2]); + nfrontp += strlen(nfrontp); + for (i = 3; i < length; i++) { + sprintf(nfrontp, " %d", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + break; + + case LM_SLC: + sprintf(nfrontp, "SLC"); + nfrontp += strlen(nfrontp); + for (i = 2; i < length - 2; i += 3) { + if (SLC_NAME_OK(pointer[i+SLC_FUNC])) + sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC])); + else + sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]); + nfrontp += strlen(nfrontp); + switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { + case SLC_NOSUPPORT: + sprintf(nfrontp, " NOSUPPORT"); break; + case SLC_CANTCHANGE: + sprintf(nfrontp, " CANTCHANGE"); break; + case SLC_VARIABLE: + sprintf(nfrontp, " VARIABLE"); break; + case SLC_DEFAULT: + sprintf(nfrontp, " DEFAULT"); break; + } + nfrontp += strlen(nfrontp); + sprintf(nfrontp, "%s%s%s", + pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", + pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); + nfrontp += strlen(nfrontp); + if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| + SLC_FLUSHOUT| SLC_LEVELBITS)) { + sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]); + nfrontp += strlen(nfrontp); + } + sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]); + nfrontp += strlen(nfrontp); + if ((pointer[i+SLC_VALUE] == IAC) && + (pointer[i+SLC_VALUE+1] == IAC)) + i++; + } + for (; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + + case LM_MODE: + sprintf(nfrontp, "MODE "); + nfrontp += strlen(nfrontp); + if (length < 3) { + sprintf(nfrontp, "(no mode??\?)"); + nfrontp += strlen(nfrontp); + break; + } + { + char tbuf[32]; + sprintf(tbuf, "%s%s%s%s%s", + pointer[2]&MODE_EDIT ? "|EDIT" : "", + pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", + pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", + pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", + pointer[2]&MODE_ACK ? "|ACK" : ""); + sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0"); + nfrontp += strlen(nfrontp); + } + if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { + sprintf(nfrontp, " (0x%x)", pointer[2]); + nfrontp += strlen(nfrontp); + } + for (i = 3; i < length; i++) { + sprintf(nfrontp, " ?0x%x?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + default: + sprintf(nfrontp, "%d (unknown)", pointer[1]); + nfrontp += strlen(nfrontp); + for (i = 2; i < length; i++) { + sprintf(nfrontp, " %d", pointer[i]); + nfrontp += strlen(nfrontp); + } + } + break; + + case TELOPT_STATUS: { + register char *cp; + register int j, k; + + sprintf(nfrontp, "STATUS"); + nfrontp += strlen(nfrontp); + + switch (pointer[1]) { + default: + if (pointer[1] == TELQUAL_SEND) + sprintf(nfrontp, " SEND"); + else + sprintf(nfrontp, " %d (unknown)", pointer[1]); + nfrontp += strlen(nfrontp); + for (i = 2; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + case TELQUAL_IS: + sprintf(nfrontp, " IS\r\n"); + nfrontp += strlen(nfrontp); + + for (i = 2; i < length; i++) { + switch(pointer[i]) { + case DO: cp = "DO"; goto common2; + case DONT: cp = "DONT"; goto common2; + case WILL: cp = "WILL"; goto common2; + case WONT: cp = "WONT"; goto common2; + common2: + i++; + if (TELOPT_OK(pointer[i])) + sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); + else + sprintf(nfrontp, " %s %d", cp, pointer[i]); + nfrontp += strlen(nfrontp); + + sprintf(nfrontp, "\r\n"); + nfrontp += strlen(nfrontp); + break; + + case SB: + sprintf(nfrontp, " SB "); + nfrontp += strlen(nfrontp); + i++; + j = k = i; + while (j < length) { + if (pointer[j] == SE) { + if (j+1 == length) + break; + if (pointer[j+1] == SE) + j++; + else + break; + } + pointer[k++] = pointer[j++]; + } + printsub(0, &pointer[i], k - i); + if (i < length) { + sprintf(nfrontp, " SE"); + nfrontp += strlen(nfrontp); + i = j; + } else + i = j - 1; + + sprintf(nfrontp, "\r\n"); + nfrontp += strlen(nfrontp); + + break; + + default: + sprintf(nfrontp, " %d", pointer[i]); + nfrontp += strlen(nfrontp); + break; + } + } + break; + } + break; + } + + case TELOPT_XDISPLOC: + sprintf(nfrontp, "X-DISPLAY-LOCATION "); + nfrontp += strlen(nfrontp); + switch (pointer[1]) { + case TELQUAL_IS: + sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); + break; + case TELQUAL_SEND: + sprintf(nfrontp, "SEND"); + break; + default: + sprintf(nfrontp, "- unknown qualifier %d (0x%x).", + pointer[1], pointer[1]); + } + nfrontp += strlen(nfrontp); + break; + + case TELOPT_NEW_ENVIRON: + sprintf(nfrontp, "NEW-ENVIRON "); + goto env_common1; + case TELOPT_OLD_ENVIRON: + sprintf(nfrontp, "OLD-ENVIRON"); + env_common1: + nfrontp += strlen(nfrontp); + switch (pointer[1]) { + case TELQUAL_IS: + sprintf(nfrontp, "IS "); + goto env_common; + case TELQUAL_SEND: + sprintf(nfrontp, "SEND "); + goto env_common; + case TELQUAL_INFO: + sprintf(nfrontp, "INFO "); + env_common: + nfrontp += strlen(nfrontp); + { + register int noquote = 2; + for (i = 2; i < length; i++ ) { + switch (pointer[i]) { + case NEW_ENV_VAR: + sprintf(nfrontp, "\" VAR " + noquote); + nfrontp += strlen(nfrontp); + noquote = 2; + break; + + case NEW_ENV_VALUE: + sprintf(nfrontp, "\" VALUE " + noquote); + nfrontp += strlen(nfrontp); + noquote = 2; + break; + + case ENV_ESC: + sprintf(nfrontp, "\" ESC " + noquote); + nfrontp += strlen(nfrontp); + noquote = 2; + break; + + case ENV_USERVAR: + sprintf(nfrontp, "\" USERVAR " + noquote); + nfrontp += strlen(nfrontp); + noquote = 2; + break; + + default: + def_case: + if (isprint(pointer[i]) && pointer[i] != '"') { + if (noquote) { + *nfrontp++ = '"'; + noquote = 0; + } + *nfrontp++ = pointer[i]; + } else { + sprintf(nfrontp, "\" %03o " + noquote, + pointer[i]); + nfrontp += strlen(nfrontp); + noquote = 2; + } + break; + } + } + if (!noquote) + *nfrontp++ = '"'; + break; + } + } + break; + +#if defined(AUTHENTICATION) + case TELOPT_AUTHENTICATION: + sprintf(nfrontp, "AUTHENTICATION"); + nfrontp += strlen(nfrontp); + + if (length < 2) { + sprintf(nfrontp, " (empty suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case TELQUAL_REPLY: + case TELQUAL_IS: + sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ? + "IS" : "REPLY"); + nfrontp += strlen(nfrontp); + if (AUTHTYPE_NAME_OK(pointer[2])) + sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2])); + else + sprintf(nfrontp, "%d ", pointer[2]); + nfrontp += strlen(nfrontp); + if (length < 3) { + sprintf(nfrontp, "(partial suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + sprintf(nfrontp, "%s|%s", + ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + nfrontp += strlen(nfrontp); + + auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + sprintf(nfrontp, "%s", buf); + nfrontp += strlen(nfrontp); + break; + + case TELQUAL_SEND: + i = 2; + sprintf(nfrontp, " SEND "); + nfrontp += strlen(nfrontp); + while (i < length) { + if (AUTHTYPE_NAME_OK(pointer[i])) + sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i])); + else + sprintf(nfrontp, "%d ", pointer[i]); + nfrontp += strlen(nfrontp); + if (++i >= length) { + sprintf(nfrontp, "(partial suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + sprintf(nfrontp, "%s|%s ", + ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? + "CLIENT" : "SERVER", + ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? + "MUTUAL" : "ONE-WAY"); + nfrontp += strlen(nfrontp); + ++i; + } + break; + + case TELQUAL_NAME: + i = 2; + sprintf(nfrontp, " NAME \""); + nfrontp += strlen(nfrontp); + while (i < length) + *nfrontp += pointer[i++]; + *nfrontp += '"'; + break; + + default: + for (i = 2; i < length; i++) { + sprintf(nfrontp, " ?%d?", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + break; +#endif + +#ifdef ENCRYPTION + case TELOPT_ENCRYPT: + sprintf(nfrontp, "ENCRYPT"); + nfrontp += strlen(nfrontp); + if (length < 2) { + sprintf(nfrontp, " (empty suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + switch (pointer[1]) { + case ENCRYPT_START: + sprintf(nfrontp, " START"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_END: + sprintf(nfrontp, " END"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_REQSTART: + sprintf(nfrontp, " REQUEST-START"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_REQEND: + sprintf(nfrontp, " REQUEST-END"); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_IS: + case ENCRYPT_REPLY: + sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ? + "IS" : "REPLY"); + nfrontp += strlen(nfrontp); + if (length < 3) { + sprintf(nfrontp, " (partial suboption??\?)"); + nfrontp += strlen(nfrontp); + break; + } + if (ENCTYPE_NAME_OK(pointer[2])) + sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2])); + else + sprintf(nfrontp, " %d (unknown)", pointer[2]); + nfrontp += strlen(nfrontp); + + encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); + sprintf(nfrontp, "%s", buf); + nfrontp += strlen(nfrontp); + break; + + case ENCRYPT_SUPPORT: + i = 2; + sprintf(nfrontp, " SUPPORT "); + nfrontp += strlen(nfrontp); + while (i < length) { + if (ENCTYPE_NAME_OK(pointer[i])) + sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i])); + else + sprintf(nfrontp, "%d ", pointer[i]); + nfrontp += strlen(nfrontp); + i++; + } + break; + + case ENCRYPT_ENC_KEYID: + sprintf(nfrontp, " ENC_KEYID", pointer[1]); + nfrontp += strlen(nfrontp); + goto encommon; + + case ENCRYPT_DEC_KEYID: + sprintf(nfrontp, " DEC_KEYID", pointer[1]); + nfrontp += strlen(nfrontp); + goto encommon; + + default: + sprintf(nfrontp, " %d (unknown)", pointer[1]); + nfrontp += strlen(nfrontp); + encommon: + for (i = 2; i < length; i++) { + sprintf(nfrontp, " %d", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + break; +#endif /* ENCRYPTION */ + + default: + if (TELOPT_OK(pointer[0])) + sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0])); + else + sprintf(nfrontp, "%d (unknown)", pointer[i]); + nfrontp += strlen(nfrontp); + for (i = 1; i < length; i++) { + sprintf(nfrontp, " %d", pointer[i]); + nfrontp += strlen(nfrontp); + } + break; + } + sprintf(nfrontp, "\r\n"); + nfrontp += strlen(nfrontp); +} + +/* + * Dump a data buffer in hex and ascii to the output data stream. + */ + void +printdata(tag, ptr, cnt) + register char *tag; + register char *ptr; + register int cnt; +{ + register int i; + char xbuf[30]; + + while (cnt) { + /* flush net output buffer if no room for new data) */ + if ((&netobuf[BUFSIZ] - nfrontp) < 80) { + netflush(); + } + + /* add a line of output */ + sprintf(nfrontp, "%s: ", tag); + nfrontp += strlen(nfrontp); + for (i = 0; i < 20 && cnt; i++) { + sprintf(nfrontp, "%02x", *ptr); + nfrontp += strlen(nfrontp); + if (isprint(*ptr)) { + xbuf[i] = *ptr; + } else { + xbuf[i] = '.'; + } + if (i % 2) { + *nfrontp = ' '; + nfrontp++; + } + cnt--; + ptr++; + } + xbuf[i] = '\0'; + sprintf(nfrontp, " %s\r\n", xbuf ); + nfrontp += strlen(nfrontp); + } +} +#endif /* DIAGNOSTICS */ diff --git a/tftp.tproj/Makefile b/tftp.tproj/Makefile new file mode 100644 index 0000000..e28658a --- /dev/null +++ b/tftp.tproj/Makefile @@ -0,0 +1,52 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = tftp + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = extern.h tftpsubs.h + +CFILES = main.c tftp.c tftpsubs.c + +OTHERSRCS = Makefile.preamble Makefile tftp.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/tftp.tproj/Makefile.preamble b/tftp.tproj/Makefile.preamble new file mode 100644 index 0000000..925a5c7 --- /dev/null +++ b/tftp.tproj/Makefile.preamble @@ -0,0 +1,3 @@ +CLEAN_ALL_SUBPROJECTS = YES +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/tftp.tproj/PB.project b/tftp.tproj/PB.project new file mode 100644 index 0000000..83d2fde --- /dev/null +++ b/tftp.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (extern.h, tftpsubs.h); + OTHER_LIBS = (); + OTHER_LINKED = (main.c, tftp.c, tftpsubs.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, tftp.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = tftp; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/tftp.tproj/extern.h b/tftp.tproj/extern.h new file mode 100644 index 0000000..f41b4d4 --- /dev/null +++ b/tftp.tproj/extern.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + */ + +void recvfile __P((int, char *, char *)); +void tftp_sendfile __P((int, char *, char *)); diff --git a/tftp.tproj/main.c b/tftp.tproj/main.c new file mode 100644 index 0000000..7e110cc --- /dev/null +++ b/tftp.tproj/main.c @@ -0,0 +1,753 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +/* Many bug fixes are from Jim Guyton */ + +/* + * TFTP User Program -- Command Interface. + */ +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +#define TIMEOUT 5 /* secs between rexmt's */ + +struct sockaddr_in peeraddr; +int f; +short port; +int trace; +int verbose; +int connected; +char mode[32]; +char line[BUFSIZ]; +int margc; +char *margv[20]; +char *prompt = "tftp"; +jmp_buf toplevel; +void intr(); +struct servent *sp; + +void get __P((int, char **)); +void help __P((int, char **)); +void modecmd __P((int, char **)); +void put __P((int, char **)); +void quit __P((int, char **)); +void setascii __P((int, char **)); +void setbinary __P((int, char **)); +void setpeer __P((int, char **)); +void setrexmt __P((int, char **)); +void settimeout __P((int, char **)); +void settrace __P((int, char **)); +void setverbose __P((int, char **)); +void status __P((int, char **)); + +static __dead void command __P((void)); + +static void getusage __P((char *)); +static void makeargv __P((void)); +static void putusage __P((char *)); +static void settftpmode __P((char *)); + +#define HELPINDENT (sizeof("connect")) + +struct cmd { + char *name; + char *help; + void (*handler) __P((int, char **)); +}; + +char vhelp[] = "toggle verbose mode"; +char thelp[] = "toggle packet tracing"; +char chelp[] = "connect to remote tftp"; +char qhelp[] = "exit tftp"; +char hhelp[] = "print help information"; +char shelp[] = "send file"; +char rhelp[] = "receive file"; +char mhelp[] = "set file transfer mode"; +char sthelp[] = "show current status"; +char xhelp[] = "set per-packet retransmission timeout"; +char ihelp[] = "set total retransmission timeout"; +char ashelp[] = "set mode to netascii"; +char bnhelp[] = "set mode to octet"; + +struct cmd cmdtab[] = { + { "connect", chelp, setpeer }, + { "mode", mhelp, modecmd }, + { "put", shelp, put }, + { "get", rhelp, get }, + { "quit", qhelp, quit }, + { "verbose", vhelp, setverbose }, + { "trace", thelp, settrace }, + { "status", sthelp, status }, + { "binary", bnhelp, setbinary }, + { "ascii", ashelp, setascii }, + { "rexmt", xhelp, setrexmt }, + { "timeout", ihelp, settimeout }, + { "?", hhelp, help }, + { 0 } +}; + +struct cmd *getcmd(); +char *tail(); +char *index(); +char *rindex(); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + struct sockaddr_in sin; + + sp = getservbyname("tftp", "udp"); + if (sp == 0) { + fprintf(stderr, "tftp: udp/tftp: unknown service\n"); + exit(1); + } + f = socket(AF_INET, SOCK_DGRAM, 0); + if (f < 0) { + perror("tftp: socket"); + exit(3); + } + bzero((char *)&sin, sizeof(sin)); + sin.sin_family = AF_INET; + if (bind(f, (struct sockaddr *)&sin, sizeof(sin)) < 0) { + perror("tftp: bind"); + exit(1); + } + strcpy(mode, "netascii"); + signal(SIGINT, intr); + if (argc > 1) { + if (setjmp(toplevel) != 0) + exit(0); + setpeer(argc, argv); + } + if (setjmp(toplevel) != 0) + (void)putchar('\n'); + command(); +} + +char hostname[100]; + +void +setpeer(argc, argv) + int argc; + char *argv[]; +{ + struct hostent *host; + + if (argc < 2) { + strcpy(line, "Connect "); + printf("(to) "); + fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin); + makeargv(); + argc = margc; + argv = margv; + } + if (argc > 3) { + printf("usage: %s host-name [port]\n", argv[0]); + return; + } + host = gethostbyname(argv[1]); + if (host) { + peeraddr.sin_family = host->h_addrtype; + bcopy(host->h_addr, &peeraddr.sin_addr, host->h_length); + strcpy(hostname, host->h_name); + } else { + peeraddr.sin_family = AF_INET; + peeraddr.sin_addr.s_addr = inet_addr(argv[1]); + if (peeraddr.sin_addr.s_addr == -1) { + connected = 0; + printf("%s: unknown host\n", argv[1]); + return; + } + strcpy(hostname, argv[1]); + } + port = sp->s_port; + if (argc == 3) { + port = atoi(argv[2]); + if (port < 0) { + printf("%s: bad port number\n", argv[2]); + connected = 0; + return; + } + port = htons(port); + } + connected = 1; +} + +struct modes { + char *m_name; + char *m_mode; +} modes[] = { + { "ascii", "netascii" }, + { "netascii", "netascii" }, + { "binary", "octet" }, + { "image", "octet" }, + { "octet", "octet" }, +/* { "mail", "mail" }, */ + { 0, 0 } +}; + +void +modecmd(argc, argv) + int argc; + char *argv[]; +{ + register struct modes *p; + char *sep; + + if (argc < 2) { + printf("Using %s mode to transfer files.\n", mode); + return; + } + if (argc == 2) { + for (p = modes; p->m_name; p++) + if (strcmp(argv[1], p->m_name) == 0) + break; + if (p->m_name) { + settftpmode(p->m_mode); + return; + } + printf("%s: unknown mode\n", argv[1]); + /* drop through and print usage message */ + } + + printf("usage: %s [", argv[0]); + sep = " "; + for (p = modes; p->m_name; p++) { + printf("%s%s", sep, p->m_name); + if (*sep == ' ') + sep = " | "; + } + printf(" ]\n"); + return; +} + +void +setbinary(argc, argv) + int argc; + char *argv[]; +{ + + settftpmode("octet"); +} + +void +setascii(argc, argv) + int argc; + char *argv[]; +{ + + settftpmode("netascii"); +} + +static void +settftpmode(newmode) + char *newmode; +{ + strcpy(mode, newmode); + if (verbose) + printf("mode set to %s\n", mode); +} + + +/* + * Send file(s). + */ +void +put(argc, argv) + int argc; + char *argv[]; +{ + int fd; + register int n; + register char *cp, *targ; + + if (argc < 2) { + strcpy(line, "send "); + printf("(file) "); + fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + putusage(argv[0]); + return; + } + targ = argv[argc - 1]; + if (index(argv[argc - 1], ':')) { + char *cp; + struct hostent *hp; + + for (n = 1; n < argc - 1; n++) + if (index(argv[n], ':')) { + putusage(argv[0]); + return; + } + cp = argv[argc - 1]; + targ = index(cp, ':'); + *targ++ = 0; + hp = gethostbyname(cp); + if (hp == NULL) { + fprintf(stderr, "tftp: %s: ", cp); + herror((char *)NULL); + return; + } + bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, hp->h_length); + peeraddr.sin_family = hp->h_addrtype; + connected = 1; + strcpy(hostname, hp->h_name); + } + if (!connected) { + printf("No target machine specified.\n"); + return; + } + if (argc < 4) { + cp = argc == 2 ? tail(targ) : argv[1]; + fd = open(cp, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "tftp: "); perror(cp); + return; + } + if (verbose) + printf("putting %s to %s:%s [%s]\n", + cp, hostname, targ, mode); + peeraddr.sin_port = port; + tftp_sendfile(fd, targ, mode); + return; + } + /* this assumes the target is a directory */ + /* on a remote unix system. hmmmm. */ + cp = index(targ, '\0'); + *cp++ = '/'; + for (n = 1; n < argc - 1; n++) { + strcpy(cp, tail(argv[n])); + fd = open(argv[n], O_RDONLY); + if (fd < 0) { + fprintf(stderr, "tftp: "); perror(argv[n]); + continue; + } + if (verbose) + printf("putting %s to %s:%s [%s]\n", + argv[n], hostname, targ, mode); + peeraddr.sin_port = port; + tftp_sendfile(fd, targ, mode); + } +} + +static void +putusage(s) + char *s; +{ + printf("usage: %s file ... host:target, or\n", s); + printf(" %s file ... target (when already connected)\n", s); +} + +/* + * Receive file(s). + */ +void +get(argc, argv) + int argc; + char *argv[]; +{ + int fd; + register int n; + register char *cp; + char *src; + + if (argc < 2) { + strcpy(line, "get "); + printf("(files) "); + fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin); + makeargv(); + argc = margc; + argv = margv; + } + if (argc < 2) { + getusage(argv[0]); + return; + } + if (!connected) { + for (n = 1; n < argc ; n++) + if (index(argv[n], ':') == 0) { + getusage(argv[0]); + return; + } + } + for (n = 1; n < argc ; n++) { + src = index(argv[n], ':'); + if (src == NULL) + src = argv[n]; + else { + struct hostent *hp; + + *src++ = 0; + hp = gethostbyname(argv[n]); + if (hp == NULL) { + fprintf(stderr, "tftp: %s: ", argv[n]); + herror((char *)NULL); + continue; + } + bcopy(hp->h_addr, (caddr_t)&peeraddr.sin_addr, + hp->h_length); + peeraddr.sin_family = hp->h_addrtype; + connected = 1; + strcpy(hostname, hp->h_name); + } + if (argc < 4) { + cp = argc == 3 ? argv[2] : tail(src); + fd = creat(cp, 0644); + if (fd < 0) { + fprintf(stderr, "tftp: "); perror(cp); + return; + } + if (verbose) + printf("getting from %s:%s to %s [%s]\n", + hostname, src, cp, mode); + peeraddr.sin_port = port; + recvfile(fd, src, mode); + break; + } + cp = tail(src); /* new .. jdg */ + fd = creat(cp, 0644); + if (fd < 0) { + fprintf(stderr, "tftp: "); perror(cp); + continue; + } + if (verbose) + printf("getting from %s:%s to %s [%s]\n", + hostname, src, cp, mode); + peeraddr.sin_port = port; + recvfile(fd, src, mode); + } +} + +static void +getusage(s) + char *s; +{ + printf("usage: %s host:file host:file ... file, or\n", s); + printf(" %s file file ... file if connected\n", s); +} + +int rexmtval = TIMEOUT; + +void +setrexmt(argc, argv) + int argc; + char *argv[]; +{ + int t; + + if (argc < 2) { + strcpy(line, "Rexmt-timeout "); + printf("(value) "); + fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin); + makeargv(); + argc = margc; + argv = margv; + } + if (argc != 2) { + printf("usage: %s value\n", argv[0]); + return; + } + t = atoi(argv[1]); + if (t < 0) + printf("%s: bad value\n", argv[1]); + else + rexmtval = t; +} + +int maxtimeout = 5 * TIMEOUT; + +void +settimeout(argc, argv) + int argc; + char *argv[]; +{ + int t; + + if (argc < 2) { + strcpy(line, "Maximum-timeout "); + printf("(value) "); + fgets(&line[strlen(line)], BUFSIZ-strlen(line)-1, stdin); + makeargv(); + argc = margc; + argv = margv; + } + if (argc != 2) { + printf("usage: %s value\n", argv[0]); + return; + } + t = atoi(argv[1]); + if (t < 0) + printf("%s: bad value\n", argv[1]); + else + maxtimeout = t; +} + +void +status(argc, argv) + int argc; + char *argv[]; +{ + if (connected) + printf("Connected to %s.\n", hostname); + else + printf("Not connected.\n"); + printf("Mode: %s Verbose: %s Tracing: %s\n", mode, + verbose ? "on" : "off", trace ? "on" : "off"); + printf("Rexmt-interval: %d seconds, Max-timeout: %d seconds\n", + rexmtval, maxtimeout); +} + +void +intr() +{ + + signal(SIGALRM, SIG_IGN); + alarm(0); + longjmp(toplevel, -1); +} + +char * +tail(filename) + char *filename; +{ + register char *s; + + while (*filename) { + s = rindex(filename, '/'); + if (s == NULL) + break; + if (s[1]) + return (s + 1); + *s = '\0'; + } + return (filename); +} + +/* + * Command parser. + */ +static __dead void +command() +{ + register struct cmd *c; + + for (;;) { + printf("%s> ", prompt); + if (fgets(line, BUFSIZ-1, stdin) == 0) { + if (feof(stdin)) { + exit(0); + } else { + continue; + } + } + if (line[0] == 0) + continue; + makeargv(); + if (margc == 0) + continue; + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + (*c->handler)(margc, margv); + } +} + +struct cmd * +getcmd(name) + register char *name; +{ + register char *p, *q; + register struct cmd *c, *found; + register int nmatches, longest; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; (p = c->name) != NULL; c++) { + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return (c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return ((struct cmd *)-1); + return (found); +} + +/* + * Slice a string up into argc/argv. + */ +static void +makeargv() +{ + register char *cp; + register char **argp = margv; + + margc = 0; + for (cp = line; *cp;) { + while (isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *argp++ = cp; + margc += 1; + while (*cp != '\0' && !isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *cp++ = '\0'; + } + *argp++ = 0; +} + +void +quit(argc, argv) + int argc; + char *argv[]; +{ + + exit(0); +} + +/* + * Help command. + */ +void +help(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + if (argc == 1) { + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c->name; c++) + printf("%-*s\t%s\n", (int)HELPINDENT, c->name, c->help); + return; + } + while (--argc > 0) { + register char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%s\n", c->help); + } +} + +void +settrace(argc, argv) + int argc; + char **argv; +{ + trace = !trace; + printf("Packet tracing %s.\n", trace ? "on" : "off"); +} + +void +setverbose(argc, argv) + int argc; + char **argv; +{ + verbose = !verbose; + printf("Verbose mode %s.\n", verbose ? "on" : "off"); +} diff --git a/tftp.tproj/tftp.1 b/tftp.tproj/tftp.1 new file mode 100644 index 0000000..b2c5a16 --- /dev/null +++ b/tftp.tproj/tftp.1 @@ -0,0 +1,173 @@ +.\" Copyright (c) 1990, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)tftp.1 8.2 (Berkeley) 4/18/94 +.\" +.Dd April 18, 1994 +.Dt TFTP 1 +.Os BSD 4.3 +.Sh NAME +.Nm tftp +.Nd trivial file transfer program +.Sh SYNOPSIS +.Nm tftp +.Op Ar host +.Sh DESCRIPTION +.Nm Tftp +is the user interface to the Internet +.Tn TFTP +(Trivial File Transfer Protocol), +which allows users to transfer files to and from a remote machine. +The remote +.Ar host +may be specified on the command line, in which case +.Nm tftp +uses +.Ar host +as the default host for future transfers (see the +.Cm connect +command below). +.Sh COMMANDS +Once +.Nm tftp +is running, it issues the prompt +.LI tftp> +and recognizes the following commands: +.Pp +.Bl -tag -width verbose -compact +.It Cm \&? Ar command-name ... +Print help information. +.Pp +.It Cm ascii +Shorthand for "mode ascii" +.Pp +.It Cm binary +Shorthand for "mode binary" +.Pp +.It Cm connect Ar host-name Op Ar port +Set the +.Ar host +(and optionally +.Ar port ) +for transfers. +Note that the +.Tn TFTP +protocol, unlike the +.Tn FTP +protocol, +does not maintain connections between transfers; thus, the +.Cm connect +command does not actually create a connection, +but merely remembers what host is to be used for transfers. +You do not have to use the +.Cm connect +command; the remote host can be specified as part of the +.Cm get +or +.Cm put +commands. +.Pp +.It Cm get Ar filename +.It Cm get Ar remotename localname +.It Cm get Ar file1 file2 ... fileN +Get a file or set of files from the specified +.Ar sources . +.Ar Source +can be in one of two forms: +a filename on the remote host, if the host has already been specified, +or a string of the form +.Ar hosts:filename +to specify both a host and filename at the same time. +If the latter form is used, +the last hostname specified becomes the default for future transfers. +.Pp +.It Cm mode Ar transfer-mode +Set the mode for transfers; +.Ar transfer-mode +may be one of +.Em ascii +or +.Em binary . +The default is +.Em ascii . +.Pp +.It Cm put Ar file +.It Cm put Ar localfile remotefile +.It Cm put Ar file1 file2 ... fileN remote-directory +Put a file or set of files to the specified +remote file or directory. +The destination +can be in one of two forms: +a filename on the remote host, if the host has already been specified, +or a string of the form +.Ar hosts:filename +to specify both a host and filename at the same time. +If the latter form is used, +the hostname specified becomes the default for future transfers. +If the remote-directory form is used, the remote host is +assumed to be a +.Tn UNIX +machine. +.Pp +.It Cm quit +Exit +.Nm tftp . +An end of file also exits. +.Pp +.It Cm rexmt Ar retransmission-timeout +Set the per-packet retransmission timeout, in seconds. +.Pp +.It Cm status +Show current status. +.Pp +.It Cm timeout Ar total-transmission-timeout +Set the total transmission timeout, in seconds. +.Pp +.It Cm trace +Toggle packet tracing. +.Pp +.It Cm verbose +Toggle verbose mode. +.El +.Sh BUGS +.Pp +Because there is no user-login or validation within +the +.Tn TFTP +protocol, the remote site will probably have some +sort of file-access restrictions in place. The +exact methods are specific to each site and therefore +difficult to document here. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/tftp.tproj/tftp.c b/tftp.tproj/tftp.c new file mode 100644 index 0000000..bec2978 --- /dev/null +++ b/tftp.tproj/tftp.c @@ -0,0 +1,474 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* Many bug fixes are from Jim Guyton */ + +/* + * TFTP User Program -- Protocol Machines + */ +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#include "extern.h" +#include "tftpsubs.h" + +extern int errno; + +extern struct sockaddr_in peeraddr; /* filled in by main */ +extern int f; /* the opened socket */ +extern int trace; +extern int verbose; +extern int rexmtval; +extern int maxtimeout; + +extern jmp_buf toplevel; /* filled in by main */ + +#define PKTSIZE SEGSIZE+4 +char ackbuf[PKTSIZE]; +int timeout; +jmp_buf timeoutbuf; + +static void nak __P((int)); +static int makerequest __P((int, const char *, struct tftphdr *, const char *)); +static void printstats __P((const char *, unsigned long)); +static void startclock __P((void)); +static void stopclock __P((void)); +static void timer __P((int)); +static void tpacket __P((const char *, struct tftphdr *, int)); + +/* + * Send the requested file. + */ +void +tftp_sendfile(fd, name, mode) + int fd; + char *name; + char *mode; +{ + register struct tftphdr *ap; /* data and ack packets */ + struct tftphdr *r_init(), *dp; + register int n; + volatile int block, size, convert; + volatile unsigned long amount; + struct sockaddr_in from; + int fromlen; + FILE *file; + + startclock(); /* start stat's clock */ + dp = r_init(); /* reset fillbuf/read-ahead code */ + ap = (struct tftphdr *)ackbuf; + file = fdopen(fd, "r"); + convert = !strcmp(mode, "netascii"); + block = 0; + amount = 0; + + signal(SIGALRM, timer); + do { + if (block == 0) + size = makerequest(WRQ, name, dp, mode) - 4; + else { + /* size = read(fd, dp->th_data, SEGSIZE); */ + size = readit(file, &dp, convert); + if (size < 0) { + nak(errno + 100); + break; + } + dp->th_opcode = htons((u_short)DATA); + dp->th_block = htons((u_short)block); + } + timeout = 0; + (void) setjmp(timeoutbuf); +send_data: + if (trace) + tpacket("sent", dp, size + 4); + n = sendto(f, dp, size + 4, 0, + (struct sockaddr *)&peeraddr, sizeof(peeraddr)); + if (n != size + 4) { + perror("tftp: sendto"); + goto abort; + } + read_ahead(file, convert); + for ( ; ; ) { + alarm(rexmtval); + do { + fromlen = sizeof(from); + n = recvfrom(f, ackbuf, sizeof(ackbuf), 0, + (struct sockaddr *)&from, &fromlen); + } while (n <= 0); + alarm(0); + if (n < 0) { + perror("tftp: recvfrom"); + goto abort; + } + peeraddr.sin_port = from.sin_port; /* added */ + if (trace) + tpacket("received", ap, n); + /* should verify packet came from server */ + ap->th_opcode = ntohs(ap->th_opcode); + ap->th_block = ntohs(ap->th_block); + if (ap->th_opcode == ERROR) { + printf("Error code %d: %s\n", ap->th_code, + ap->th_msg); + goto abort; + } + if (ap->th_opcode == ACK) { + int j; + + if (ap->th_block == block) { + break; + } + /* On an error, try to synchronize + * both sides. + */ + j = synchnet(f); + if (j && trace) { + printf("discarded %d packets\n", + j); + } + if (ap->th_block == (block-1)) { + goto send_data; + } + } + } + if (block > 0) + amount += size; + block++; + } while (size == SEGSIZE || block == 1); +abort: + fclose(file); + stopclock(); + if (amount > 0) + printstats("Sent", amount); +} + +/* + * Receive a file. + */ +void +recvfile(fd, name, mode) + int fd; + char *name; + char *mode; +{ + register struct tftphdr *ap; + struct tftphdr *dp, *w_init(); + register int n; + volatile int block, size, firsttrip; + volatile unsigned long amount; + struct sockaddr_in from; + int fromlen; + FILE *file; + volatile int convert; /* true if converting crlf -> lf */ + + startclock(); + dp = w_init(); + ap = (struct tftphdr *)ackbuf; + file = fdopen(fd, "w"); + convert = !strcmp(mode, "netascii"); + block = 1; + firsttrip = 1; + amount = 0; + + signal(SIGALRM, timer); + do { + if (firsttrip) { + size = makerequest(RRQ, name, ap, mode); + firsttrip = 0; + } else { + ap->th_opcode = htons((u_short)ACK); + ap->th_block = htons((u_short)(block)); + size = 4; + block++; + } + timeout = 0; + (void) setjmp(timeoutbuf); +send_ack: + if (trace) + tpacket("sent", ap, size); + if (sendto(f, ackbuf, size, 0, (struct sockaddr *)&peeraddr, + sizeof(peeraddr)) != size) { + alarm(0); + perror("tftp: sendto"); + goto abort; + } + write_behind(file, convert); + for ( ; ; ) { + alarm(rexmtval); + do { + fromlen = sizeof(from); + n = recvfrom(f, dp, PKTSIZE, 0, + (struct sockaddr *)&from, &fromlen); + } while (n <= 0); + alarm(0); + if (n < 0) { + perror("tftp: recvfrom"); + goto abort; + } + peeraddr.sin_port = from.sin_port; /* added */ + if (trace) + tpacket("received", dp, n); + /* should verify client address */ + dp->th_opcode = ntohs(dp->th_opcode); + dp->th_block = ntohs(dp->th_block); + if (dp->th_opcode == ERROR) { + printf("Error code %d: %s\n", dp->th_code, + dp->th_msg); + goto abort; + } + if (dp->th_opcode == DATA) { + int j; + + if (dp->th_block == block) { + break; /* have next packet */ + } + /* On an error, try to synchronize + * both sides. + */ + j = synchnet(f); + if (j && trace) { + printf("discarded %d packets\n", j); + } + if (dp->th_block == (block-1)) { + goto send_ack; /* resend ack */ + } + } + } + /* size = write(fd, dp->th_data, n - 4); */ + size = writeit(file, &dp, n - 4, convert); + if (size < 0) { + nak(errno + 100); + break; + } + amount += size; + } while (size == SEGSIZE); +abort: /* ok to ack, since user */ + ap->th_opcode = htons((u_short)ACK); /* has seen err msg */ + ap->th_block = htons((u_short)block); + (void) sendto(f, ackbuf, 4, 0, (struct sockaddr *)&peeraddr, + sizeof(peeraddr)); + write_behind(file, convert); /* flush last buffer */ + fclose(file); + stopclock(); + if (amount > 0) + printstats("Received", amount); +} + +static int +makerequest(request, name, tp, mode) + int request; + const char *name; + struct tftphdr *tp; + const char *mode; +{ + register char *cp; + + tp->th_opcode = htons((u_short)request); + cp = tp->th_stuff; + strcpy(cp, name); + cp += strlen(name); + *cp++ = '\0'; + strcpy(cp, mode); + cp += strlen(mode); + *cp++ = '\0'; + return (cp - (char *)tp); +} + +struct errmsg { + int e_code; + char *e_msg; +} errmsgs[] = { + { EUNDEF, "Undefined error code" }, + { ENOTFOUND, "File not found" }, + { EACCESS, "Access violation" }, + { ENOSPACE, "Disk full or allocation exceeded" }, + { EBADOP, "Illegal TFTP operation" }, + { EBADID, "Unknown transfer ID" }, + { EEXISTS, "File already exists" }, + { ENOUSER, "No such user" }, + { -1, 0 } +}; + +/* + * Send a nak packet (error message). + * Error code passed in is one of the + * standard TFTP codes, or a UNIX errno + * offset by 100. + */ +static void +nak(error) + int error; +{ + register struct errmsg *pe; + register struct tftphdr *tp; + int length; + char *strerror(); + + tp = (struct tftphdr *)ackbuf; + tp->th_opcode = htons((u_short)ERROR); + tp->th_code = htons((u_short)error); + for (pe = errmsgs; pe->e_code >= 0; pe++) + if (pe->e_code == error) + break; + if (pe->e_code < 0) { + pe->e_msg = strerror(error - 100); + tp->th_code = EUNDEF; + } + strcpy(tp->th_msg, pe->e_msg); + length = strlen(pe->e_msg) + 4; + if (trace) + tpacket("sent", tp, length); + if (sendto(f, ackbuf, length, 0, (struct sockaddr *)&peeraddr, + sizeof(peeraddr)) != length) + perror("nak"); +} + +static void +tpacket(s, tp, n) + const char *s; + struct tftphdr *tp; + int n; +{ + static char *opcodes[] = + { "#0", "RRQ", "WRQ", "DATA", "ACK", "ERROR" }; + register char *cp, *file; + u_short op = ntohs(tp->th_opcode); + char *index(); + + if (op < RRQ || op > ERROR) + printf("%s opcode=%x ", s, op); + else + printf("%s %s ", s, opcodes[op]); + switch (op) { + + case RRQ: + case WRQ: + n -= 2; + file = cp = tp->th_stuff; + cp = index(cp, '\0'); + printf("\n", file, cp + 1); + break; + + case DATA: + printf("\n", ntohs(tp->th_block), n - 4); + break; + + case ACK: + printf("\n", ntohs(tp->th_block)); + break; + + case ERROR: + printf("\n", ntohs(tp->th_code), tp->th_msg); + break; + } +} + +struct timeval tstart; +struct timeval tstop; + +static void +startclock() +{ + + (void)gettimeofday(&tstart, NULL); +} + +static void +stopclock() +{ + + (void)gettimeofday(&tstop, NULL); +} + +static void +printstats(direction, amount) + const char *direction; + unsigned long amount; +{ + double delta; + /* compute delta in 1/10's second units */ + delta = ((tstop.tv_sec*10.)+(tstop.tv_usec/100000)) - + ((tstart.tv_sec*10.)+(tstart.tv_usec/100000)); + delta = delta/10.; /* back to seconds */ + printf("%s %d bytes in %.1f seconds", direction, amount, delta); + if (verbose) + printf(" [%.0f bits/sec]", (amount*8.)/delta); + putchar('\n'); +} + +static void +timer(sig) + int sig; +{ + + timeout += rexmtval; + if (timeout >= maxtimeout) { + printf("Transfer timed out.\n"); + longjmp(toplevel, -1); + } + longjmp(timeoutbuf, 1); +} diff --git a/tftp.tproj/tftpsubs.c b/tftp.tproj/tftpsubs.c new file mode 100644 index 0000000..f63504a --- /dev/null +++ b/tftp.tproj/tftpsubs.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* Simple minded read-ahead/write-behind subroutines for tftp user and + server. Written originally with multiple buffers in mind, but current + implementation has two buffer logic wired in. + + Todo: add some sort of final error check so when the write-buffer + is finally flushed, the caller can detect if the disk filled up + (or had an i/o error) and return a nak to the other side. + + Jim Guyton 10/85 + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "tftpsubs.h" + +#define PKTSIZE SEGSIZE+4 /* should be moved to tftp.h */ + +struct bf { + int counter; /* size of data in buffer, or flag */ + char buf[PKTSIZE]; /* room for data packet */ +} bfs[2]; + + /* Values for bf.counter */ +#define BF_ALLOC -3 /* alloc'd but not yet filled */ +#define BF_FREE -2 /* free */ +/* [-1 .. SEGSIZE] = size of data in the data buffer */ + +static int nextone; /* index of next buffer to use */ +static int current; /* index of buffer in use */ + + /* control flags for crlf conversions */ +int newline = 0; /* fillbuf: in middle of newline expansion */ +int prevchar = -1; /* putbuf: previous char (cr check) */ + +static struct tftphdr *rw_init(); + +struct tftphdr *w_init() { return rw_init(0); } /* write-behind */ +struct tftphdr *r_init() { return rw_init(1); } /* read-ahead */ + +static struct tftphdr * +rw_init(x) /* init for either read-ahead or write-behind */ + int x; /* zero for write-behind, one for read-head */ +{ + newline = 0; /* init crlf flag */ + prevchar = -1; + bfs[0].counter = BF_ALLOC; /* pass out the first buffer */ + current = 0; + bfs[1].counter = BF_FREE; + nextone = x; /* ahead or behind? */ + return (struct tftphdr *)bfs[0].buf; +} + + +/* Have emptied current buffer by sending to net and getting ack. + Free it and return next buffer filled with data. + */ +int +readit(file, dpp, convert) + FILE *file; /* file opened for read */ + struct tftphdr **dpp; + int convert; /* if true, convert to ascii */ +{ + struct bf *b; + + bfs[current].counter = BF_FREE; /* free old one */ + current = !current; /* "incr" current */ + + b = &bfs[current]; /* look at new buffer */ + if (b->counter == BF_FREE) /* if it's empty */ + read_ahead(file, convert); /* fill it */ +/* assert(b->counter != BF_FREE);*//* check */ + *dpp = (struct tftphdr *)b->buf; /* set caller's ptr */ + return b->counter; +} + +/* + * fill the input buffer, doing ascii conversions if requested + * conversions are lf -> cr,lf and cr -> cr, nul + */ +void +read_ahead(file, convert) + FILE *file; /* file opened for read */ + int convert; /* if true, convert to ascii */ +{ + register int i; + register char *p; + register int c; + struct bf *b; + struct tftphdr *dp; + + b = &bfs[nextone]; /* look at "next" buffer */ + if (b->counter != BF_FREE) /* nop if not free */ + return; + nextone = !nextone; /* "incr" next buffer ptr */ + + dp = (struct tftphdr *)b->buf; + + if (convert == 0) { + b->counter = read(fileno(file), dp->th_data, SEGSIZE); + return; + } + + p = dp->th_data; + for (i = 0 ; i < SEGSIZE; i++) { + if (newline) { + if (prevchar == '\n') + c = '\n'; /* lf to cr,lf */ + else c = '\0'; /* cr to cr,nul */ + newline = 0; + } + else { + c = getc(file); + if (c == EOF) break; + if (c == '\n' || c == '\r') { + prevchar = c; + c = '\r'; + newline = 1; + } + } + *p++ = c; + } + b->counter = (int)(p - dp->th_data); +} + +/* Update count associated with the buffer, get new buffer + from the queue. Calls write_behind only if next buffer not + available. + */ +int +writeit(file, dpp, ct, convert) + FILE *file; + struct tftphdr **dpp; + int ct, convert; +{ + bfs[current].counter = ct; /* set size of data to write */ + current = !current; /* switch to other buffer */ + if (bfs[current].counter != BF_FREE) /* if not free */ + (void)write_behind(file, convert); /* flush it */ + bfs[current].counter = BF_ALLOC; /* mark as alloc'd */ + *dpp = (struct tftphdr *)bfs[current].buf; + return ct; /* this is a lie of course */ +} + +/* + * Output a buffer to a file, converting from netascii if requested. + * CR,NUL -> CR and CR,LF => LF. + * Note spec is undefined if we get CR as last byte of file or a + * CR followed by anything else. In this case we leave it alone. + */ +int +write_behind(file, convert) + FILE *file; + int convert; +{ + char *buf; + int count; + register int ct; + register char *p; + register int c; /* current character */ + struct bf *b; + struct tftphdr *dp; + + b = &bfs[nextone]; + if (b->counter < -1) /* anything to flush? */ + return 0; /* just nop if nothing to do */ + + count = b->counter; /* remember byte count */ + b->counter = BF_FREE; /* reset flag */ + dp = (struct tftphdr *)b->buf; + nextone = !nextone; /* incr for next time */ + buf = dp->th_data; + + if (count <= 0) return -1; /* nak logic? */ + + if (convert == 0) + return write(fileno(file), buf, count); + + p = buf; + ct = count; + while (ct--) { /* loop over the buffer */ + c = *p++; /* pick up a character */ + if (prevchar == '\r') { /* if prev char was cr */ + if (c == '\n') /* if have cr,lf then just */ + fseek(file, -1, 1); /* smash lf on top of the cr */ + else + if (c == '\0') /* if have cr,nul then */ + goto skipit; /* just skip over the putc */ + /* else just fall through and allow it */ + } + putc(c, file); +skipit: + prevchar = c; + } + return count; +} + + +/* When an error has occurred, it is possible that the two sides + * are out of synch. Ie: that what I think is the other side's + * response to packet N is really their response to packet N-1. + * + * So, to try to prevent that, we flush all the input queued up + * for us on the network connection on our host. + * + * We return the number of packets we flushed (mostly for reporting + * when trace is active). + */ + +int +synchnet(f) + int f; /* socket to flush */ +{ + int i, j = 0; + char rbuf[PKTSIZE]; + struct sockaddr_in from; + int fromlen; + + while (1) { + (void) ioctl(f, FIONREAD, &i); + if (i) { + j++; + fromlen = sizeof from; + (void) recvfrom(f, rbuf, sizeof (rbuf), 0, + (struct sockaddr *)&from, &fromlen); + } else { + return(j); + } + } +} diff --git a/tftp.tproj/tftpsubs.h b/tftp.tproj/tftpsubs.h new file mode 100644 index 0000000..9ecb2d2 --- /dev/null +++ b/tftp.tproj/tftpsubs.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)tftpsubs.h 8.1 (Berkeley) 6/6/93 + */ + +/* + * Prototypes for read-ahead/write-behind subroutines for tftp user and + * server. + */ +struct tftphdr *r_init __P((void)); +void read_ahead __P((FILE *, int)); +int readit __P((FILE *, struct tftphdr **, int)); + +int synchnet __P((int)); + +struct tftphdr *w_init __P((void)); +int write_behind __P((FILE *, int)); +int writeit __P((FILE *, struct tftphdr **, int, int)); diff --git a/tftpd.tproj/Makefile b/tftpd.tproj/Makefile new file mode 100644 index 0000000..8ce74c9 --- /dev/null +++ b/tftpd.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = tftpd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = tftpd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble tftpd.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + +HEADER_PATHS = -I../tftp.tproj + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/tftpd.tproj/Makefile.postamble b/tftpd.tproj/Makefile.postamble new file mode 100644 index 0000000..382a280 --- /dev/null +++ b/tftpd.tproj/Makefile.postamble @@ -0,0 +1,112 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + +VPATH += :../tftp.tproj diff --git a/tftpd.tproj/Makefile.preamble b/tftpd.tproj/Makefile.preamble new file mode 100644 index 0000000..8a2e16a --- /dev/null +++ b/tftpd.tproj/Makefile.preamble @@ -0,0 +1,121 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +OTHER_OFILES = tftpsubs.o + +-include ../Makefile.include diff --git a/tftpd.tproj/PB.project b/tftpd.tproj/PB.project new file mode 100644 index 0000000..39cfa7e --- /dev/null +++ b/tftpd.tproj/PB.project @@ -0,0 +1,41 @@ +{ + FILESTABLE = { + C_FILES = (); + HEADERSEARCH = (../tftp.tproj); + H_FILES = (); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (tftpd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, tftpd.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = tftpd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/tftpd.tproj/tftpd.8 b/tftpd.tproj/tftpd.8 new file mode 100644 index 0000000..430c1c4 --- /dev/null +++ b/tftpd.tproj/tftpd.8 @@ -0,0 +1,106 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)tftpd.8 8.1 (Berkeley) 6/4/93 +.\" +.Dd June 4, 1993 +.Dt TFTPD 8 +.Os BSD 4.2 +.Sh NAME +.Nm tftpd +.Nd +Internet Trivial File Transfer Protocol server +.Sh SYNOPSIS +.Nm tftpd +.Op Fl l +.Op Fl n +.Op Ar directory ... +.Sh DESCRIPTION +.Nm Tftpd +is a server which supports the +Internet Trivial File Transfer +Protocol (\c +.Tn RFC 783). +The +.Tn TFTP +server operates +at the port indicated in the +.Ql tftp +service description; +see +.Xr services 5 . +The server is normally started by +.Xr inetd 8 . +.Pp +The use of +.Xr tftp 1 +does not require an account or password on the remote system. +Due to the lack of authentication information, +.Nm tftpd +will allow only publicly readable files to be +accessed. +Files containing the string ``/\|\fB.\|.\fP\|/'' are not allowed. +Files may be written only if they already exist and are publicly writable. +Note that this extends the concept of +.Dq public +to include +all users on all hosts that can be reached through the network; +this may not be appropriate on all systems, and its implications +should be considered before enabling tftp service. +The server should have the user ID with the lowest possible privilege. +.Pp +Access to files may be restricted by invoking +.Nm tftpd +with a list of directories by including up to 20 pathnames +as server program arguments in +.Pa /etc/inetd.conf . +In this case access is restricted to files whose +names are prefixed by the one of the given directories. +The given directories are also treated as a search path for +relative filename requests. +.Pp +The options are: +.Bl -tag -width Ds +.It Fl l +Logs all requests using +.Xr syslog 3 . +.It Fl n +Suppresses negative acknowledgement of requests for nonexistent +relative filenames. +.El +.Sh SEE ALSO +.Xr tftp 1 , +.Xr inetd 8 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/tftpd.tproj/tftpd.c b/tftpd.tproj/tftpd.c new file mode 100644 index 0000000..f73cb56 --- /dev/null +++ b/tftpd.tproj/tftpd.c @@ -0,0 +1,673 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * Trivial file transfer protocol server. + * + * This version includes many modifications by Jim Guyton + * . + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tftpsubs.h" + +#define TIMEOUT 5 + +int peer; +int rexmtval = TIMEOUT; +int maxtimeout = 5*TIMEOUT; + +#define PKTSIZE SEGSIZE+4 +char buf[PKTSIZE]; +char ackbuf[PKTSIZE]; +struct sockaddr_in from; +int fromlen; + +void tftp __P((struct tftphdr *, int)); + +/* + * Null-terminated directory prefix list for absolute pathname requests and + * search list for relative pathname requests. + * + * MAXDIRS should be at least as large as the number of arguments that + * inetd allows (currently 20). + */ +#define MAXDIRS 20 +static struct dirlist { + char *name; + int len; +} dirs[MAXDIRS+1]; +static int suppress_naks; +static int logging; + +static char *errtomsg __P((int)); +static void nak __P((int)); +static char *verifyhost __P((struct sockaddr_in *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register struct tftphdr *tp; + register int n; + int ch, on; + struct sockaddr_in sin; + + openlog("tftpd", LOG_PID, LOG_FTP); + while ((ch = getopt(argc, argv, "ln")) != EOF) { + switch (ch) { + case 'l': + logging = 1; + break; + case 'n': + suppress_naks = 1; + break; + default: + syslog(LOG_WARNING, "ignoring unknown option -%c", ch); + } + } + if (optind < argc) { + struct dirlist *dirp; + + /* Get list of directory prefixes. Skip relative pathnames. */ + for (dirp = dirs; optind < argc && dirp < &dirs[MAXDIRS]; + optind++) { + if (argv[optind][0] == '/') { + dirp->name = argv[optind]; + dirp->len = strlen(dirp->name); + dirp++; + } + } + } + + on = 1; + if (ioctl(0, FIONBIO, &on) < 0) { + syslog(LOG_ERR, "ioctl(FIONBIO): %m\n"); + exit(1); + } + fromlen = sizeof (from); + n = recvfrom(0, buf, sizeof (buf), 0, + (struct sockaddr *)&from, &fromlen); + if (n < 0) { + syslog(LOG_ERR, "recvfrom: %m\n"); + exit(1); + } + /* + * Now that we have read the message out of the UDP + * socket, we fork and exit. Thus, inetd will go back + * to listening to the tftp port, and the next request + * to come in will start up a new instance of tftpd. + * + * We do this so that inetd can run tftpd in "wait" mode. + * The problem with tftpd running in "nowait" mode is that + * inetd may get one or more successful "selects" on the + * tftp port before we do our receive, so more than one + * instance of tftpd may be started up. Worse, if tftpd + * break before doing the above "recvfrom", inetd would + * spawn endless instances, clogging the system. + */ + { + int pid; + int i, j; + + for (i = 1; i < 20; i++) { + pid = fork(); + if (pid < 0) { + sleep(i); + /* + * flush out to most recently sent request. + * + * This may drop some request, but those + * will be resent by the clients when + * they timeout. The positive effect of + * this flush is to (try to) prevent more + * than one tftpd being started up to service + * a single request from a single client. + */ + j = sizeof from; + i = recvfrom(0, buf, sizeof (buf), 0, + (struct sockaddr *)&from, &j); + if (i > 0) { + n = i; + fromlen = j; + } + } else { + break; + } + } + if (pid < 0) { + syslog(LOG_ERR, "fork: %m\n"); + exit(1); + } else if (pid != 0) { + exit(0); + } + } + from.sin_family = AF_INET; + alarm(0); + close(0); + close(1); + peer = socket(AF_INET, SOCK_DGRAM, 0); + if (peer < 0) { + syslog(LOG_ERR, "socket: %m\n"); + exit(1); + } + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + if (bind(peer, (struct sockaddr *)&sin, sizeof (sin)) < 0) { + syslog(LOG_ERR, "bind: %m\n"); + exit(1); + } + if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) { + syslog(LOG_ERR, "connect: %m\n"); + exit(1); + } + tp = (struct tftphdr *)buf; + tp->th_opcode = ntohs(tp->th_opcode); + if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) + tftp(tp, n); + exit(1); +} + +struct formats; +int validate_access __P((char **, int)); +void tftp_sendfile __P((struct formats *)); +void recvfile __P((struct formats *)); + +struct formats { + char *f_mode; + int (*f_validate) __P((char **, int)); + void (*f_send) __P((struct formats *)); + void (*f_recv) __P((struct formats *)); + int f_convert; +} formats[] = { + { "netascii", validate_access, tftp_sendfile, recvfile, 1 }, + { "octet", validate_access, tftp_sendfile, recvfile, 0 }, +#ifdef notdef + { "mail", validate_user, sendmail, recvmail, 1 }, +#endif + { 0 } +}; + +/* + * Handle initial connection protocol. + */ +void +tftp(tp, size) + struct tftphdr *tp; + int size; +{ + register char *cp; + int first = 1, ecode; + register struct formats *pf; + char *filename, *mode; + + filename = cp = tp->th_stuff; +again: + while (cp < buf + size) { + if (*cp == '\0') + break; + cp++; + } + if (*cp != '\0') { + nak(EBADOP); + exit(1); + } + if (first) { + mode = ++cp; + first = 0; + goto again; + } + for (cp = mode; *cp; cp++) + if (isupper(*cp)) + *cp = tolower(*cp); + for (pf = formats; pf->f_mode; pf++) + if (strcmp(pf->f_mode, mode) == 0) + break; + if (pf->f_mode == 0) { + nak(EBADOP); + exit(1); + } + ecode = (*pf->f_validate)(&filename, tp->th_opcode); + if (logging) { + syslog(LOG_INFO, "%s: %s request for %s: %s", + verifyhost(&from), + tp->th_opcode == WRQ ? "write" : "read", + filename, errtomsg(ecode)); + } + if (ecode) { + /* + * Avoid storms of naks to a RRQ broadcast for a relative + * bootfile pathname from a diskless Sun. + */ + if (suppress_naks && *filename != '/' && ecode == ENOTFOUND) + exit(0); + nak(ecode); + exit(1); + } + if (tp->th_opcode == WRQ) + (*pf->f_recv)(pf); + else + (*pf->f_send)(pf); + exit(0); +} + + +FILE *file; + +/* + * Validate file access. Since we + * have no uid or gid, for now require + * file to exist and be publicly + * readable/writable. + * If we were invoked with arguments + * from inetd then the file must also be + * in one of the given directory prefixes. + * Note also, full path name must be + * given as we have no login directory. + */ +int +validate_access(filep, mode) + char **filep; + int mode; +{ + struct stat stbuf; + int fd; + struct dirlist *dirp; + static char pathname[MAXPATHLEN]; + char *filename = *filep; + + /* + * Prevent tricksters from getting around the directory restrictions + */ + if (strstr(filename, "/../")) + return (EACCESS); + + if (*filename == '/') { + /* + * Allow the request if it's in one of the approved locations. + * Special case: check the null prefix ("/") by looking + * for length = 1 and relying on the arg. processing that + * it's a /. + */ + for (dirp = dirs; dirp->name != NULL; dirp++) { + if (dirp->len == 1 || + (!strncmp(filename, dirp->name, dirp->len) && + filename[dirp->len] == '/')) + break; + } + /* If directory list is empty, allow access to any file */ + if (dirp->name == NULL && dirp != dirs) + return (EACCESS); + if (stat(filename, &stbuf) < 0) + return (errno == ENOENT ? ENOTFOUND : EACCESS); + if ((stbuf.st_mode & S_IFMT) != S_IFREG) + return (ENOTFOUND); + if (mode == RRQ) { + if ((stbuf.st_mode & S_IROTH) == 0) + return (EACCESS); + } else { + if ((stbuf.st_mode & S_IWOTH) == 0) + return (EACCESS); + } + } else { + int err; + + /* + * Relative file name: search the approved locations for it. + * Don't allow write requests or ones that avoid directory + * restrictions. + */ + + if (mode != RRQ || !strncmp(filename, "../", 3)) + return (EACCESS); + + /* + * If the file exists in one of the directories and isn't + * readable, continue looking. However, change the error code + * to give an indication that the file exists. + */ + err = ENOTFOUND; + for (dirp = dirs; dirp->name != NULL; dirp++) { + sprintf(pathname, "%s/%s", dirp->name, filename); + if (stat(pathname, &stbuf) == 0 && + (stbuf.st_mode & S_IFMT) == S_IFREG) { + if ((stbuf.st_mode & S_IROTH) != 0) { + break; + } + err = EACCESS; + } + } + if (dirp->name == NULL) + return (err); + *filep = filename = pathname; + } + fd = open(filename, mode == RRQ ? 0 : 1); + if (fd < 0) + return (errno + 100); + file = fdopen(fd, (mode == RRQ)? "r":"w"); + if (file == NULL) { + return errno+100; + } + return (0); +} + +int timeout; +jmp_buf timeoutbuf; + +void +timer() +{ + + timeout += rexmtval; + if (timeout >= maxtimeout) + exit(1); + longjmp(timeoutbuf, 1); +} + +/* + * Send the requested file. + */ +void +tftp_sendfile(pf) + struct formats *pf; +{ + struct tftphdr *dp, *r_init(); + register struct tftphdr *ap; /* ack packet */ + register int size, n; + volatile int block; + + signal(SIGALRM, timer); + dp = r_init(); + ap = (struct tftphdr *)ackbuf; + block = 1; + do { + size = readit(file, &dp, pf->f_convert); + if (size < 0) { + nak(errno + 100); + goto abort; + } + dp->th_opcode = htons((u_short)DATA); + dp->th_block = htons((u_short)block); + timeout = 0; + (void)setjmp(timeoutbuf); + +send_data: + if (send(peer, dp, size + 4, 0) != size + 4) { + syslog(LOG_ERR, "tftpd: write: %m\n"); + goto abort; + } + read_ahead(file, pf->f_convert); + for ( ; ; ) { + alarm(rexmtval); /* read the ack */ + n = recv(peer, ackbuf, sizeof (ackbuf), 0); + alarm(0); + if (n < 0) { + syslog(LOG_ERR, "tftpd: read: %m\n"); + goto abort; + } + ap->th_opcode = ntohs((u_short)ap->th_opcode); + ap->th_block = ntohs((u_short)ap->th_block); + + if (ap->th_opcode == ERROR) + goto abort; + + if (ap->th_opcode == ACK) { + if (ap->th_block == block) + break; + /* Re-synchronize with the other side */ + (void) synchnet(peer); + if (ap->th_block == (block -1)) + goto send_data; + } + + } + block++; + } while (size == SEGSIZE); +abort: + (void) fclose(file); +} + +void +justquit() +{ + exit(0); +} + + +/* + * Receive a file. + */ +void +recvfile(pf) + struct formats *pf; +{ + struct tftphdr *dp, *w_init(); + register struct tftphdr *ap; /* ack buffer */ + register int n, size; + volatile int block; + + signal(SIGALRM, timer); + dp = w_init(); + ap = (struct tftphdr *)ackbuf; + block = 0; + do { + timeout = 0; + ap->th_opcode = htons((u_short)ACK); + ap->th_block = htons((u_short)block); + block++; + (void) setjmp(timeoutbuf); +send_ack: + if (send(peer, ackbuf, 4, 0) != 4) { + syslog(LOG_ERR, "tftpd: write: %m\n"); + goto abort; + } + write_behind(file, pf->f_convert); + for ( ; ; ) { + alarm(rexmtval); + n = recv(peer, dp, PKTSIZE, 0); + alarm(0); + if (n < 0) { /* really? */ + syslog(LOG_ERR, "tftpd: read: %m\n"); + goto abort; + } + dp->th_opcode = ntohs((u_short)dp->th_opcode); + dp->th_block = ntohs((u_short)dp->th_block); + if (dp->th_opcode == ERROR) + goto abort; + if (dp->th_opcode == DATA) { + if (dp->th_block == block) { + break; /* normal */ + } + /* Re-synchronize with the other side */ + (void) synchnet(peer); + if (dp->th_block == (block-1)) + goto send_ack; /* rexmit */ + } + } + /* size = write(file, dp->th_data, n - 4); */ + size = writeit(file, &dp, n - 4, pf->f_convert); + if (size != (n-4)) { /* ahem */ + if (size < 0) nak(errno + 100); + else nak(ENOSPACE); + goto abort; + } + } while (size == SEGSIZE); + write_behind(file, pf->f_convert); + (void) fclose(file); /* close data file */ + + ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */ + ap->th_block = htons((u_short)(block)); + (void) send(peer, ackbuf, 4, 0); + + signal(SIGALRM, justquit); /* just quit on timeout */ + alarm(rexmtval); + n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */ + alarm(0); + if (n >= 4 && /* if read some data */ + dp->th_opcode == DATA && /* and got a data block */ + block == dp->th_block) { /* then my last ack was lost */ + (void) send(peer, ackbuf, 4, 0); /* resend final ack */ + } +abort: + return; +} + +struct errmsg { + int e_code; + char *e_msg; +} errmsgs[] = { + { EUNDEF, "Undefined error code" }, + { ENOTFOUND, "File not found" }, + { EACCESS, "Access violation" }, + { ENOSPACE, "Disk full or allocation exceeded" }, + { EBADOP, "Illegal TFTP operation" }, + { EBADID, "Unknown transfer ID" }, + { EEXISTS, "File already exists" }, + { ENOUSER, "No such user" }, + { -1, 0 } +}; + +static char * +errtomsg(error) + int error; +{ + static char buf[20]; + register struct errmsg *pe; + if (error == 0) + return "success"; + for (pe = errmsgs; pe->e_code >= 0; pe++) + if (pe->e_code == error) + return pe->e_msg; + sprintf(buf, "error %d", error); + return buf; +} + +/* + * Send a nak packet (error message). + * Error code passed in is one of the + * standard TFTP codes, or a UNIX errno + * offset by 100. + */ +static void +nak(error) + int error; +{ + register struct tftphdr *tp; + int length; + register struct errmsg *pe; + + tp = (struct tftphdr *)buf; + tp->th_opcode = htons((u_short)ERROR); + tp->th_code = htons((u_short)error); + for (pe = errmsgs; pe->e_code >= 0; pe++) + if (pe->e_code == error) + break; + if (pe->e_code < 0) { + pe->e_msg = strerror(error - 100); + tp->th_code = EUNDEF; /* set 'undef' errorcode */ + } + strcpy(tp->th_msg, pe->e_msg); + length = strlen(pe->e_msg); + tp->th_msg[length] = '\0'; + length += 5; + if (send(peer, buf, length, 0) != length) + syslog(LOG_ERR, "nak: %m\n"); +} + +static char * +verifyhost(fromp) + struct sockaddr_in *fromp; +{ + struct hostent *hp; + + hp = gethostbyaddr((char *)&fromp->sin_addr, sizeof (fromp->sin_addr), + fromp->sin_family); + if (hp) + return hp->h_name; + else + return inet_ntoa(fromp->sin_addr); +} diff --git a/timed.tproj/Makefile b/timed.tproj/Makefile new file mode 100644 index 0000000..fc8a78d --- /dev/null +++ b/timed.tproj/Makefile @@ -0,0 +1,44 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = timed + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Aggregate + +TOOLS = timed.tproj timedc.tproj + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = aggregate.make +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/timed.tproj/Makefile.postamble b/timed.tproj/Makefile.postamble new file mode 100644 index 0000000..18167b9 --- /dev/null +++ b/timed.tproj/Makefile.postamble @@ -0,0 +1,109 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. diff --git a/timed.tproj/Makefile.preamble b/timed.tproj/Makefile.preamble new file mode 100644 index 0000000..cc5c371 --- /dev/null +++ b/timed.tproj/Makefile.preamble @@ -0,0 +1,121 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libs to link against +OTHER_LIBS = +# Additional libs to link against when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +-include ../Makefile.include diff --git a/timed.tproj/PB.project b/timed.tproj/PB.project new file mode 100644 index 0000000..624995d --- /dev/null +++ b/timed.tproj/PB.project @@ -0,0 +1,21 @@ +{ + FILESTABLE = { + H_FILES = (); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + SUBPROJECTS = (timed.tproj, timedc.tproj); + TOOLS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = timed; + PROJECTTYPE = Aggregate; + PROJECTVERSION = 2.8; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/timed.tproj/timed.tproj/Makefile b/timed.tproj/timed.tproj/Makefile new file mode 100644 index 0000000..8636bc9 --- /dev/null +++ b/timed.tproj/timed.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = timed + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = extern.h globals.h pathnames.h + +CFILES = acksend.c byteorder.c candidate.c cksum.c correct.c master.c\ + measure.c networkdelta.c readmsg.c slave.c timed.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble timed.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/timed.tproj/timed.tproj/Makefile.postamble b/timed.tproj/timed.tproj/Makefile.postamble new file mode 100644 index 0000000..36381d4 --- /dev/null +++ b/timed.tproj/timed.tproj/Makefile.postamble @@ -0,0 +1,122 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/timed.tproj/timed.tproj/Makefile.preamble b/timed.tproj/timed.tproj/Makefile.preamble new file mode 100644 index 0000000..74ce95a --- /dev/null +++ b/timed.tproj/timed.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/timed.tproj/timed.tproj/PB.project b/timed.tproj/timed.tproj/PB.project new file mode 100644 index 0000000..e3accbc --- /dev/null +++ b/timed.tproj/timed.tproj/PB.project @@ -0,0 +1,38 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (extern.h, globals.h, pathnames.h); + OTHER_LINKED = ( + acksend.c, + byteorder.c, + candidate.c, + cksum.c, + correct.c, + master.c, + measure.c, + networkdelta.c, + readmsg.c, + slave.c, + timed.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, timed.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = timed; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/timed.tproj/timed.tproj/acksend.c b/timed.tproj/timed.tproj/acksend.c new file mode 100644 index 0000000..af1aea0 --- /dev/null +++ b/timed.tproj/timed.tproj/acksend.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)acksend.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" + +struct tsp *answer; + +extern u_short sequence; + +void +xmit(type, seq, addr) + int type; + u_int seq; + struct sockaddr_in *addr; +{ + static struct tsp msg; + + msg.tsp_type = type; + msg.tsp_seq = seq; + msg.tsp_vers = TSPVERSION; + (void)strcpy(msg.tsp_name, hostname); + bytenetorder(&msg); + if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, + (struct sockaddr*)addr, sizeof(struct sockaddr)) < 0) { + trace_sendto_err(addr->sin_addr); + } +} + + +/* + * Acksend implements reliable datagram transmission by using sequence + * numbers and retransmission when necessary. + * If `name' is ANYADDR, this routine implements reliable broadcast. + * + * Because this function calls readmsg(), none of its args may be in + * a message provided by readmsg(). + */ +struct tsp * +acksend(message, addr, name, ack, net, bad) + struct tsp *message; /* this message */ + struct sockaddr_in *addr; /* to here */ + char *name; + int ack; /* look for this ack */ + struct netinfo *net; /* receive from this network */ + int bad; /* 1=losing patience */ +{ + struct timeval twait; + int count; + long msec; + + message->tsp_vers = TSPVERSION; + message->tsp_seq = sequence; + if (trace) { + fprintf(fd, "acksend: to %s: ", + (name == ANYADDR ? "broadcast" : name)); + print(message, addr); + } + bytenetorder(message); + + msec = 200; + count = bad ? 1 : 5; /* 5 packets in 6.4 seconds */ + answer = 0; + do { + if (!answer) { + /* do not go crazy transmitting just because the + * other guy cannot keep our sequence numbers + * straight. + */ + if (sendto(sock, (char *)message, sizeof(struct tsp), + 0, (struct sockaddr*)addr, + sizeof(struct sockaddr)) < 0) { + trace_sendto_err(addr->sin_addr); + break; + } + } + + mstotvround(&twait, msec); + answer = readmsg(ack, name, &twait, net); + if (answer != 0) { + if (answer->tsp_seq != sequence) { + if (trace) + fprintf(fd,"acksend: seq # %u!=%u\n", + answer->tsp_seq, sequence); + continue; + } + break; + } + + msec *= 2; + } while (--count > 0); + sequence++; + + return(answer); +} diff --git a/timed.tproj/timed.tproj/byteorder.c b/timed.tproj/timed.tproj/byteorder.c new file mode 100644 index 0000000..97bb911 --- /dev/null +++ b/timed.tproj/timed.tproj/byteorder.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)byteorder.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" + +/* + * Two routines to do the necessary byte swapping for timed protocol + * messages. Protocol is defined in /usr/include/protocols/timed.h + */ +void +bytenetorder(ptr) + struct tsp *ptr; +{ + ptr->tsp_seq = htons((u_short)ptr->tsp_seq); + switch (ptr->tsp_type) { + + case TSP_SETTIME: + case TSP_ADJTIME: + case TSP_SETDATE: + case TSP_SETDATEREQ: + ptr->tsp_time.tv_sec = htonl((u_long)ptr->tsp_time.tv_sec); + ptr->tsp_time.tv_usec = htonl((u_long)ptr->tsp_time.tv_usec); + break; + + default: + break; /* nothing more needed */ + } +} + +void +bytehostorder(ptr) + struct tsp *ptr; +{ + ptr->tsp_seq = ntohs((u_short)ptr->tsp_seq); + switch (ptr->tsp_type) { + + case TSP_SETTIME: + case TSP_ADJTIME: + case TSP_SETDATE: + case TSP_SETDATEREQ: + ptr->tsp_time.tv_sec = ntohl((u_long)ptr->tsp_time.tv_sec); + ptr->tsp_time.tv_usec = ntohl((u_long)ptr->tsp_time.tv_usec); + break; + + default: + break; /* nothing more needed */ + } +} diff --git a/timed.tproj/timed.tproj/candidate.c b/timed.tproj/timed.tproj/candidate.c new file mode 100644 index 0000000..a271db5 --- /dev/null +++ b/timed.tproj/timed.tproj/candidate.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)candidate.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" + +/* + * `election' candidates a host as master: it is called by a slave + * which runs with the -M option set when its election timeout expires. + * Note the conservative approach: if a new timed comes up, or another + * candidate sends an election request, the candidature is withdrawn. + */ +int +election(net) + struct netinfo *net; +{ + struct tsp *resp, msg; + struct timeval then, wait; + struct tsp *answer; + struct hosttbl *htp; + char loop_lim = 0; + +/* This code can get totally confused if it gets slightly behind. For + * example, if readmsg() has some QUIT messages waiting from the last + * round, we would send an ELECTION message, get the stale QUIT, + * and give up. This results in network storms when several machines + * do it at once. + */ + wait.tv_sec = 0; + wait.tv_usec = 0; + while (0 != readmsg(TSP_REFUSE, ANYADDR, &wait, net)) { + if (trace) + fprintf(fd, "election: discarded stale REFUSE\n"); + } + while (0 != readmsg(TSP_QUIT, ANYADDR, &wait, net)) { + if (trace) + fprintf(fd, "election: discarded stale QUIT\n"); + } + +again: + syslog(LOG_INFO, "This machine is a candidate time master"); + if (trace) + fprintf(fd, "This machine is a candidate time master\n"); + msg.tsp_type = TSP_ELECTION; + msg.tsp_vers = TSPVERSION; + (void)strcpy(msg.tsp_name, hostname); + bytenetorder(&msg); + if (sendto(sock, (char *)&msg, sizeof(struct tsp), 0, + (struct sockaddr*)&net->dest_addr, + sizeof(struct sockaddr)) < 0) { + trace_sendto_err(net->dest_addr.sin_addr); + return(SLAVE); + } + + (void)gettimeofday(&then, 0); + then.tv_sec += 3; + for (;;) { + (void)gettimeofday(&wait, 0); + timevalsub(&wait,&then,&wait); + resp = readmsg(TSP_ANY, ANYADDR, &wait, net); + if (!resp) + return(MASTER); + + switch (resp->tsp_type) { + + case TSP_ACCEPT: + (void)addmach(resp->tsp_name, &from,fromnet); + break; + + case TSP_MASTERUP: + case TSP_MASTERREQ: + /* + * If another timedaemon is coming up at the same + * time, give up, and let it be the master. + */ + if (++loop_lim < 5 + && !good_host_name(resp->tsp_name)) { + (void)addmach(resp->tsp_name, &from,fromnet); + suppress(&from, resp->tsp_name, net); + goto again; + } + rmnetmachs(net); + return(SLAVE); + + case TSP_QUIT: + case TSP_REFUSE: + /* + * Collision: change value of election timer + * using exponential backoff. + * + * Fooey. + * An exponential backoff on a delay starting at + * 6 to 15 minutes for a process that takes + * milliseconds is silly. It is particularly + * strange that the original code would increase + * the backoff without bound. + */ + rmnetmachs(net); + return(SLAVE); + + case TSP_ELECTION: + /* no master for another round */ + htp = addmach(resp->tsp_name,&from,fromnet); + msg.tsp_type = TSP_REFUSE; + (void)strcpy(msg.tsp_name, hostname); + answer = acksend(&msg, &htp->addr, htp->name, + TSP_ACK, 0, htp->noanswer); + if (!answer) { + syslog(LOG_ERR, "error in election from %s", + htp->name); + } + break; + + case TSP_SLAVEUP: + (void)addmach(resp->tsp_name, &from,fromnet); + break; + + case TSP_SETDATE: + case TSP_SETDATEREQ: + break; + + default: + if (trace) { + fprintf(fd, "candidate: "); + print(resp, &from); + } + break; + } + } +} diff --git a/timed.tproj/timed.tproj/cksum.c b/timed.tproj/timed.tproj/cksum.c new file mode 100644 index 0000000..e50e438 --- /dev/null +++ b/timed.tproj/timed.tproj/cksum.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cksum.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include + +/* + * I N _ C K S U M + * + * Checksum routine for Internet Protocol family headers (C Version) + * + * There is no profit in a specialized version of the checksum + * function for any machine where int's are 32 bits and shorts are 16. + * + * All timed packets are smaller than 32K shorts, so there is no need to + * worry about carries except at the end. + */ +int +in_cksum(addr, len) + u_short *addr; + int len; +{ + register int nleft = len; + register u_short *w = addr; + register u_short answer; + register int sum = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while( nleft > 1 ) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if( nleft == 1 ) + sum += (*(u_char *)w) << 8; + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} diff --git a/timed.tproj/timed.tproj/correct.c b/timed.tproj/timed.tproj/correct.c new file mode 100644 index 0000000..f092bca --- /dev/null +++ b/timed.tproj/timed.tproj/correct.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)correct.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" +#include +#include +#include +#ifdef sgi +#include +#endif /* sgi */ + +static void adjclock __P((struct timeval *)); + +/* + * sends to the slaves the corrections for their clocks after fixing our + * own + */ +void +correct(avdelta) + long avdelta; +{ + struct hosttbl *htp; + int corr; + struct timeval adjlocal; + struct tsp to; + struct tsp *answer; + + mstotvround(&adjlocal, avdelta); + + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + if (htp->delta != HOSTDOWN) { + corr = avdelta - htp->delta; +/* If the other machine is off in the weeds, set its time directly. + * If a slave gets the wrong day, the original code would simply + * fix the minutes. If you fix a network partition, you can get + * into such situations. + */ + if (htp->need_set + || corr >= MAXADJ*1000 + || corr <= -MAXADJ*1000) { + htp->need_set = 0; + (void)gettimeofday(&to.tsp_time,0); + timevaladd(&to.tsp_time, &adjlocal); + to.tsp_type = TSP_SETTIME; + } else { + mstotvround(&to.tsp_time, corr); + to.tsp_type = TSP_ADJTIME; + } + (void)strcpy(to.tsp_name, hostname); + answer = acksend(&to, &htp->addr, htp->name, + TSP_ACK, 0, 0); + if (!answer) { + htp->delta = HOSTDOWN; + syslog(LOG_WARNING, + "no reply to time correction from %s", + htp->name); + if (++htp->noanswer >= LOSTHOST) { + if (trace) { + fprintf(fd, + "purging %s for not answering\n", + htp->name); + (void)fflush(fd); + } + htp = remmach(htp); + } + } + } + } + + /* + * adjust our own clock now that we are not sending it out + */ + adjclock(&adjlocal); +} + + +static void +adjclock(corr) + struct timeval *corr; +{ + static int passes = 0; + static int smoother = 0; + long delta; /* adjustment in usec */ + long ndelta; + struct timeval now; + struct timeval adj; + + if (!timerisset(corr)) + return; + + adj = *corr; + if (adj.tv_sec < MAXADJ && adj.tv_sec > - MAXADJ) { + delta = adj.tv_sec*1000000 + adj.tv_usec; + /* If the correction is less than the minimum round + * trip time for an ICMP packet, and thus + * less than the likely error in the measurement, + * do not do the entire correction. Do half + * or a quarter of it. + */ + + if (delta > -MIN_ROUND*1000 + && delta < MIN_ROUND*1000) { + if (smoother <= 4) + smoother++; + ndelta = delta >> smoother; + if (trace) + fprintf(fd, + "trimming delta %ld usec to %ld\n", + delta, ndelta); + adj.tv_usec = ndelta; + adj.tv_sec = 0; + } else if (smoother > 0) { + smoother--; + } + if (0 > adjtime(corr, 0)) { + syslog(LOG_ERR, "adjtime: %m"); + } + if (passes > 1 + && (delta < -BIG_ADJ || delta > BIG_ADJ)) { + smoother = 0; + passes = 0; + syslog(LOG_WARNING, + "large time adjustment of %+.3f sec", + delta/1000000.0); + } + } else { + syslog(LOG_WARNING, + "clock correction %d sec too large to adjust", + adj.tv_sec); + (void) gettimeofday(&now, 0); + timevaladd(&now, corr); + if (settimeofday(&now, 0) < 0) + syslog(LOG_ERR, "settimeofday: %m"); + } + +#ifdef sgi + /* Accumulate the total change, and use it to adjust the basic + * clock rate. + */ + if (++passes > 2) { +#define F_USEC_PER_SEC (1000000*1.0) /* reduce typos */ +#define F_NSEC_PER_SEC (F_USEC_PER_SEC*1000.0) + + extern char *timetrim_fn; + extern char *timetrim_wpat; + extern long timetrim; + extern double tot_adj, hr_adj; /* totals in nsec */ + extern double tot_ticks, hr_ticks; + + static double nag_tick; + double cur_ticks, hr_delta_ticks, tot_delta_ticks; + double tru_tot_adj, tru_hr_adj; /* nsecs of adjustment */ + double tot_trim, hr_trim; /* nsec/sec */ + struct tms tm; + FILE *timetrim_st; + + cur_ticks = times(&tm); + tot_adj += delta*1000.0; + hr_adj += delta*1000.0; + + tot_delta_ticks = cur_ticks-tot_ticks; + if (tot_delta_ticks >= 16*SECDAY*CLK_TCK) { + tot_adj -= rint(tot_adj/16); + tot_ticks += rint(tot_delta_ticks/16); + tot_delta_ticks = cur_ticks-tot_ticks; + } + hr_delta_ticks = cur_ticks-hr_ticks; + + tru_hr_adj = hr_adj + timetrim*rint(hr_delta_ticks/CLK_TCK); + tru_tot_adj = (tot_adj + + timetrim*rint(tot_delta_ticks/CLK_TCK)); + + if (hr_delta_ticks >= SECDAY*CLK_TCK + || (tot_delta_ticks < 4*SECDAY*CLK_TCK + && hr_delta_ticks >= SECHR*CLK_TCK) + || (trace && hr_delta_ticks >= (SECHR/10)*CLK_TCK)) { + + tot_trim = rint(tru_tot_adj*CLK_TCK/tot_delta_ticks); + hr_trim = rint(tru_hr_adj*CLK_TCK/hr_delta_ticks); + + if (trace + || (abs(timetrim - hr_trim) > 100000.0 + && 0 == timetrim_fn + && ((cur_ticks - nag_tick) + >= 24*SECDAY*CLK_TCK))) { + nag_tick = cur_ticks; + syslog(LOG_NOTICE, + "%+.3f/%.2f or %+.3f/%.2f sec/hr; timetrim=%+.0f or %+.0f", + tru_tot_adj/F_NSEC_PER_SEC, + tot_delta_ticks/(SECHR*CLK_TCK*1.0), + tru_hr_adj/F_NSEC_PER_SEC, + hr_delta_ticks/(SECHR*CLK_TCK*1.0), + tot_trim, + hr_trim); + } + + if (tot_trim < -MAX_TRIM || tot_trim > MAX_TRIM) { + tot_ticks = hr_ticks; + tot_adj = hr_adj; + } else if (0 > syssgi(SGI_SETTIMETRIM, + (long)tot_trim)) { + syslog(LOG_ERR, "SETTIMETRIM(%d): %m", + (long)tot_trim); + } else { + if (0 != timetrim_fn) { + timetrim_st = fopen(timetrim_fn, "w"); + if (0 == timetrim_st) { + syslog(LOG_ERR, "fopen(%s): %m", + timetrim_fn); + } else { + if (0 > fprintf(timetrim_st, + timetrim_wpat, + (long)tot_trim, + tru_tot_adj, + tot_delta_ticks)) { + syslog(LOG_ERR, + "fprintf(%s): %m", + timetrim_fn); + } + (void)fclose(timetrim_st); + } + } + + tot_adj -= ((tot_trim - timetrim) + * rint(tot_delta_ticks/CLK_TCK)); + timetrim = tot_trim; + } + + hr_ticks = cur_ticks; + hr_adj = 0; + } + } +#endif /* sgi */ +} + + +/* adjust the time in a message by the time it + * spent in the queue + */ +void +adj_msg_time(msg, now) + struct tsp *msg; + struct timeval *now; +{ + msg->tsp_time.tv_sec += (now->tv_sec - from_when.tv_sec); + msg->tsp_time.tv_usec += (now->tv_usec - from_when.tv_usec); + + while (msg->tsp_time.tv_usec < 0) { + msg->tsp_time.tv_sec--; + msg->tsp_time.tv_usec += 1000000; + } + while (msg->tsp_time.tv_usec >= 1000000) { + msg->tsp_time.tv_sec++; + msg->tsp_time.tv_usec -= 1000000; + } +} diff --git a/timed.tproj/timed.tproj/extern.h b/timed.tproj/timed.tproj/extern.h new file mode 100644 index 0000000..00f9d35 --- /dev/null +++ b/timed.tproj/timed.tproj/extern.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + */ + +struct hosttbl; +struct netinfo; +struct sockaddr_in; +struct timeval; +struct tsp; + +struct hosttbl *addmach __P((char *, struct sockaddr_in *, struct netinfo *)); +struct hosttbl *findhost __P((char *)); +struct hosttbl *remmach __P((struct hosttbl *)); + +struct tsp *readmsg __P((int, + char *, struct timeval *, struct netinfo *)); +struct tsp *acksend __P((struct tsp *, + struct sockaddr_in *, char *, int, struct netinfo *, int)); + +void addnetname __P((char *)); +void adj_msg_time __P((struct tsp *, struct timeval *)); +void bytehostorder __P((struct tsp *)); +void bytenetorder __P((struct tsp *)); +void byteorder __P((struct tsp *)); +long casual __P((long, long)); +int cksum __P((u_short *, int)); +void correct __P((long)); +char *date __P((void)); +void doquit __P((struct tsp *)); +int election __P((struct netinfo *)); +void get_goodgroup __P((int)); +int good_host_name __P((char *)); +void ignoreack __P((void)); +int in_cksum __P((u_short *, int)); +void lookformaster __P((struct netinfo *)); +void makeslave __P((struct netinfo *)); +int master __P((void)); +void masterack __P((void)); +void masterup __P((struct netinfo *)); +int measure __P((u_long, u_long, char *, struct sockaddr_in *, int)); +void msterup __P((struct netinfo *)); +void mstotvround __P((struct timeval *, long)); +long networkdelta __P((void)); +void newslave __P((struct tsp *)); +void print __P((struct tsp *, struct sockaddr_in *)); +void prthp __P((clock_t)); +void rmnetmachs __P((struct netinfo *)); +void setstatus __P((void)); +int slave __P((void)); +void slaveack __P((void)); +void spreadtime __P((void)); +void suppress __P((struct sockaddr_in *, char *, struct netinfo *)); +void synch __P((long)); +void timevaladd __P((struct timeval *, struct timeval *)); +void timevalsub __P((struct timeval *, struct timeval *, struct timeval *)); +void traceoff __P((char *)); +void traceon __P((void)); +void xmit __P((int, u_int, struct sockaddr_in *)); diff --git a/timed.tproj/timed.tproj/globals.h b/timed.tproj/timed.tproj/globals.h new file mode 100644 index 0000000..82cfc53 --- /dev/null +++ b/timed.tproj/timed.tproj/globals.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)globals.h 8.1 (Berkeley) 6/6/93 + */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifdef sgi +#include +#include +/* use the constant HZ instead of the function CLK_TCK */ +#undef CLK_TCK +#define CLK_TCK HZ +#else +#define SECHR (60*60) +#define SECDAY (24*SECHR) +#endif /* sgi */ + +extern int errno; +extern int sock; + +/* Best expected round trip for a measurement. + * This is essentially the number of milliseconds per CPU tick (CLK_TCK?). + * All delays shorter than this are usually reported as 0. + */ +#define MIN_ROUND ((1000-1)/CLK_TCK) + + +#define SAMPLEINTVL 240 /* synch() freq for master in sec */ +#define MAXADJ 20 /* max adjtime() correction in sec */ + +#define MAX_TRIM 3000000 /* max drift in nsec/sec, 0.3% */ +#define BIG_ADJ (MAX_TRIM/1000*SAMPLEINTVL*2) /* max good adj */ + +#define MINTOUT 360 /* election delays, 6-15 minutes */ +#define MAXTOUT 900 + +#define BAD_STATUS (-1) +#define GOOD 1 +#define UNREACHABLE 2 +#define NONSTDTIME 3 +#define HOSTDOWN 0x7fffffff + +#define OFF 0 +#define ON 1 + +#define MAX_HOPCNT 10 /* max value for tsp_hpcnt */ + +#define LOSTHOST 3 /* forget after this many failures */ + +#define VALID_RANGE (MAXADJ*1000) /* good times in milliseconds */ +#define GOOD_RANGE (MIN_ROUND*2) +#define VGOOD_RANGE (MIN_ROUND-1) + + +/* + * Global and per-network states. + */ +#define NOMASTER 0 /* no good master */ +#define SLAVE 1 +#define MASTER 2 +#define IGNORE 4 +#define ALL (SLAVE|MASTER|IGNORE) +#define SUBMASTER (SLAVE|MASTER) + +#define NHOSTS 1013 /* max of hosts controlled by timed + * This must be a prime number. + */ +struct hosttbl { + struct hosttbl *h_bak; /* hash chain */ + struct hosttbl *h_fwd; + struct hosttbl *l_bak; /* "sequential" list */ + struct hosttbl *l_fwd; + struct netinfo *ntp; + struct sockaddr_in addr; + char name[MAXHOSTNAMELEN+1]; + u_char head; /* 1=head of hash chain */ + u_char good; /* 0=trusted host, for averaging */ + u_char noanswer; /* count of failures to answer */ + u_char need_set; /* need a SETTIME */ + u_short seq; + long delta; +}; + +/* closed hash table with internal chaining */ +extern struct hosttbl hosttbl[NHOSTS+1]; +#define self hosttbl[0] +#define hostname (self.name) + + +struct netinfo { + struct netinfo *next; + struct in_addr net; + u_long mask; + struct in_addr my_addr; + struct sockaddr_in dest_addr; /* broadcast addr or point-point */ + long status; + struct timeval slvwait; /* delay before sending our time */ + int quit_count; /* recent QUITs */ +}; + +#include "extern.h" + +#define tvtomsround(tv) ((tv).tv_sec*1000 + ((tv).tv_usec + 500)/1000) + +extern struct netinfo *nettab; +extern int status; +extern int trace; +extern int sock; +extern struct sockaddr_in from; +extern struct timeval from_when; /* when the last msg arrived */ +extern u_short sequence; /* TSP message sequence number */ +extern struct netinfo *fromnet, *slavenet; +extern FILE *fd; +extern long delay1, delay2; +extern int nslavenets; /* nets were I could be a slave */ +extern int nmasternets; /* nets were I could be a master */ +extern int nignorednets; /* ignored nets */ +extern int nnets; /* nets I am connected to */ + + +#define trace_msg(msg) {if (trace) fprintf(fd, msg);} + +#define trace_sendto_err(addr) { \ + int st_errno = errno; \ + syslog(LOG_ERR, "%s %d: sendto %s: %m", \ + __FILE__, __LINE__, inet_ntoa(addr)); \ + if (trace) \ + fprintf(fd, "%s %d: sendto %s: %d", __FILE__, __LINE__, \ + inet_ntoa(addr), st_errno); \ +} + + +# define max(a,b) (ab ? b : a) +# define abs(x) (x>=0 ? x : -(x)) diff --git a/timed.tproj/timed.tproj/master.c b/timed.tproj/timed.tproj/master.c new file mode 100644 index 0000000..ddd3215 --- /dev/null +++ b/timed.tproj/timed.tproj/master.c @@ -0,0 +1,930 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)master.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" +#include +#include +#include +#include +#ifdef sgi +#include +#endif /* sgi */ +#include +#include "pathnames.h" + +extern int measure_delta; +extern jmp_buf jmpenv; +extern int Mflag; +extern int justquit; + +static int dictate; +static int slvcount; /* slaves listening to our clock */ + +static void mchgdate __P((struct tsp *)); + +#ifdef sgi +extern void logwtmp __P((struct timeval *, struct timeval *)); +#else +extern void logwtmp __P((char *, char *, char *)); +#endif /* sgi */ + +/* + * The main function of `master' is to periodically compute the differences + * (deltas) between its clock and the clocks of the slaves, to compute the + * network average delta, and to send to the slaves the differences between + * their individual deltas and the network delta. + * While waiting, it receives messages from the slaves (i.e. requests for + * master's name, remote requests to set the network time, ...), and + * takes the appropriate action. + */ +int +master() +{ + struct hosttbl *htp; + long pollingtime; +#define POLLRATE 4 + int polls; + struct timeval wait, ntime; + struct tsp *msg, *answer, to; + char newdate[32]; + struct sockaddr_in taddr; + char tname[MAXHOSTNAMELEN]; + struct netinfo *ntp; + int i; + + syslog(LOG_NOTICE, "This machine is master"); + if (trace) + fprintf(fd, "This machine is master\n"); + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == MASTER) + masterup(ntp); + } + (void)gettimeofday(&ntime, 0); + pollingtime = ntime.tv_sec+3; + if (justquit) + polls = 0; + else + polls = POLLRATE-1; + +/* Process all outstanding messages before spending the long time necessary + * to update all timers. + */ +loop: + (void)gettimeofday(&ntime, 0); + wait.tv_sec = pollingtime - ntime.tv_sec; + if (wait.tv_sec < 0) + wait.tv_sec = 0; + wait.tv_usec = 0; + msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); + if (!msg) { + (void)gettimeofday(&ntime, 0); + if (ntime.tv_sec >= pollingtime) { + pollingtime = ntime.tv_sec + SAMPLEINTVL; + get_goodgroup(0); + +/* If a bogus master told us to quit, we can have decided to ignore a + * network. Therefore, periodically try to take over everything. + */ + polls = (polls + 1) % POLLRATE; + if (0 == polls && nignorednets > 0) { + trace_msg("Looking for nets to re-master\n"); + for (ntp = nettab; ntp; ntp = ntp->next) { + if (ntp->status == IGNORE + || ntp->status == NOMASTER) { + lookformaster(ntp); + if (ntp->status == MASTER) { + masterup(ntp); + polls = POLLRATE-1; + } + } + if (ntp->status == MASTER + && --ntp->quit_count < 0) + ntp->quit_count = 0; + } + if (polls != 0) + setstatus(); + } + + synch(0L); + + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + to.tsp_type = TSP_LOOP; + to.tsp_vers = TSPVERSION; + to.tsp_seq = sequence++; + to.tsp_hopcnt = MAX_HOPCNT; + (void)strcpy(to.tsp_name, hostname); + bytenetorder(&to); + if (sendto(sock, (char *)&to, + sizeof(struct tsp), 0, + (struct sockaddr*)&ntp->dest_addr, + sizeof(ntp->dest_addr)) < 0) { + trace_sendto_err(ntp->dest_addr.sin_addr); + } + } + } + + + } else { + switch (msg->tsp_type) { + + case TSP_MASTERREQ: + break; + + case TSP_SLAVEUP: + newslave(msg); + break; + + case TSP_SETDATE: + /* + * XXX check to see it is from ourself + */ +#ifdef sgi + (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); +#else + (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); +#endif /* sgi */ + if (!good_host_name(msg->tsp_name)) { + syslog(LOG_NOTICE, + "attempted date change by %s to %s", + msg->tsp_name, newdate); + spreadtime(); + break; + } + + mchgdate(msg); + (void)gettimeofday(&ntime, 0); + pollingtime = ntime.tv_sec + SAMPLEINTVL; + break; + + case TSP_SETDATEREQ: + if (!fromnet || fromnet->status != MASTER) + break; +#ifdef sgi + (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); +#else + (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); +#endif /* sgi */ + htp = findhost(msg->tsp_name); + if (htp == 0) { + syslog(LOG_ERR, + "attempted SET DATEREQ by uncontrolled %s to %s", + msg->tsp_name, newdate); + break; + } + if (htp->seq == msg->tsp_seq) + break; + htp->seq = msg->tsp_seq; + if (!htp->good) { + syslog(LOG_NOTICE, + "attempted SET DATEREQ by untrusted %s to %s", + msg->tsp_name, newdate); + spreadtime(); + break; + } + + mchgdate(msg); + (void)gettimeofday(&ntime, 0); + pollingtime = ntime.tv_sec + SAMPLEINTVL; + break; + + case TSP_MSITE: + xmit(TSP_ACK, msg->tsp_seq, &from); + break; + + case TSP_MSITEREQ: + break; + + case TSP_TRACEON: + traceon(); + break; + + case TSP_TRACEOFF: + traceoff("Tracing ended at %s\n"); + break; + + case TSP_ELECTION: + if (!fromnet) + break; + if (fromnet->status == MASTER) { + pollingtime = 0; + (void)addmach(msg->tsp_name, &from,fromnet); + } + taddr = from; + (void)strcpy(tname, msg->tsp_name); + to.tsp_type = TSP_QUIT; + (void)strcpy(to.tsp_name, hostname); + answer = acksend(&to, &taddr, tname, + TSP_ACK, 0, 1); + if (answer == NULL) { + syslog(LOG_ERR, "election error by %s", + tname); + } + break; + + case TSP_CONFLICT: + /* + * After a network partition, there can be + * more than one master: the first slave to + * come up will notify here the situation. + */ + if (!fromnet || fromnet->status != MASTER) + break; + (void)strcpy(to.tsp_name, hostname); + + /* The other master often gets into the same state, + * with boring results if we stay at it forever. + */ + ntp = fromnet; /* (acksend() can leave fromnet=0 */ + for (i = 0; i < 3; i++) { + to.tsp_type = TSP_RESOLVE; + (void)strcpy(to.tsp_name, hostname); + answer = acksend(&to, &ntp->dest_addr, + ANYADDR, TSP_MASTERACK, + ntp, 0); + if (!answer) + break; + htp = addmach(answer->tsp_name,&from,ntp); + to.tsp_type = TSP_QUIT; + msg = acksend(&to, &htp->addr, htp->name, + TSP_ACK, 0, htp->noanswer); + if (msg == NULL) { + syslog(LOG_ERR, + "no response from %s to CONFLICT-QUIT", + htp->name); + } + } + masterup(ntp); + pollingtime = 0; + break; + + case TSP_RESOLVE: + if (!fromnet || fromnet->status != MASTER) + break; + /* + * do not want to call synch() while waiting + * to be killed! + */ + (void)gettimeofday(&ntime, (struct timezone *)0); + pollingtime = ntime.tv_sec + SAMPLEINTVL; + break; + + case TSP_QUIT: + doquit(msg); /* become a slave */ + break; + + case TSP_LOOP: + if (!fromnet || fromnet->status != MASTER + || !strcmp(msg->tsp_name, hostname)) + break; + /* + * We should not have received this from a net + * we are master on. There must be two masters. + */ + htp = addmach(msg->tsp_name, &from,fromnet); + to.tsp_type = TSP_QUIT; + (void)strcpy(to.tsp_name, hostname); + answer = acksend(&to, &htp->addr, htp->name, + TSP_ACK, 0, 1); + if (!answer) { + syslog(LOG_WARNING, + "loop breakage: no reply from %s=%s to QUIT", + htp->name, inet_ntoa(htp->addr.sin_addr)); + (void)remmach(htp); + } + + case TSP_TEST: + if (trace) { + fprintf(fd, + "\tnets = %d, masters = %d, slaves = %d, ignored = %d\n", + nnets, nmasternets, nslavenets, nignorednets); + setstatus(); + } + pollingtime = 0; + polls = POLLRATE-1; + break; + + default: + if (trace) { + fprintf(fd, "garbage message: "); + print(msg, &from); + } + break; + } + } + goto loop; +} + + +/* + * change the system date on the master + */ +static void +mchgdate(msg) + struct tsp *msg; +{ + char tname[MAXHOSTNAMELEN]; + char olddate[32]; + struct timeval otime, ntime; + + (void)strcpy(tname, msg->tsp_name); + + xmit(TSP_DATEACK, msg->tsp_seq, &from); + + (void)strcpy(olddate, date()); + + /* adjust time for residence on the queue */ + (void)gettimeofday(&otime, 0); + adj_msg_time(msg,&otime); + + timevalsub(&ntime, &msg->tsp_time, &otime); + if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { + /* + * do not change the clock if we can adjust it + */ + dictate = 3; + synch(tvtomsround(ntime)); + } else { +#ifdef sgi + if (0 > settimeofday(&msg->tsp_time, 0)) { + syslog(LOG_ERR, "settimeofday(): %m"); + } + logwtmp(&otime, &msg->tsp_time); +#else + logwtmp("|", "date", ""); + (void)settimeofday(&msg->tsp_time, 0); + logwtmp("}", "date", ""); +#endif /* sgi */ + spreadtime(); + } + + syslog(LOG_NOTICE, "date changed by %s from %s", + tname, olddate); +} + + +/* + * synchronize all of the slaves + */ +void +synch(mydelta) + long mydelta; +{ + struct hosttbl *htp; + int measure_status; + struct timeval check, stop, wait; +#ifdef sgi + int pri; +#endif /* sgi */ + + if (slvcount > 0) { + if (trace) + fprintf(fd, "measurements starting at %s\n", date()); + (void)gettimeofday(&check, 0); +#ifdef sgi + /* run fast to get good time */ + pri = schedctl(NDPRI,0,NDPHIMIN); + if (pri < 0) + syslog(LOG_ERR, "schedctl(): %m"); +#endif /* sgi */ + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + if (htp->noanswer != 0) { + measure_status = measure(500, 100, + htp->name, + &htp->addr,0); + } else { + measure_status = measure(3000, 100, + htp->name, + &htp->addr,0); + } + if (measure_status != GOOD) { + /* The slave did not respond. We have + * just wasted lots of time on it. + */ + htp->delta = HOSTDOWN; + if (++htp->noanswer >= LOSTHOST) { + if (trace) { + fprintf(fd, + "purging %s for not answering ICMP\n", + htp->name); + (void)fflush(fd); + } + htp = remmach(htp); + } + } else { + htp->delta = measure_delta; + } + (void)gettimeofday(&stop, 0); + timevalsub(&stop, &stop, &check); + if (stop.tv_sec >= 1) { + if (trace) + (void)fflush(fd); + /* + * ack messages periodically + */ + wait.tv_sec = 0; + wait.tv_usec = 0; + if (0 != readmsg(TSP_TRACEON,ANYADDR, + &wait,0)) + traceon(); + (void)gettimeofday(&check, 0); + } + } +#ifdef sgi + if (pri >= 0) + (void)schedctl(NDPRI,0,pri); +#endif /* sgi */ + if (trace) + fprintf(fd, "measurements finished at %s\n", date()); + } + if (!(status & SLAVE)) { + if (!dictate) { + mydelta = networkdelta(); + } else { + dictate--; + } + } + if (trace && (mydelta != 0 || (status & SLAVE))) + fprintf(fd,"local correction of %ld ms.\n", mydelta); + correct(mydelta); +} + +/* + * sends the time to each slave after the master + * has received the command to set the network time + */ +void +spreadtime() +{ + struct hosttbl *htp; + struct tsp to; + struct tsp *answer; + +/* Do not listen to the consensus after forcing the time. This is because + * the consensus takes a while to reach the time we are dictating. + */ + dictate = 2; + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + to.tsp_type = TSP_SETTIME; + (void)strcpy(to.tsp_name, hostname); + (void)gettimeofday(&to.tsp_time, 0); + answer = acksend(&to, &htp->addr, htp->name, + TSP_ACK, 0, htp->noanswer); + if (answer == 0) { + /* We client does not respond, then we have + * just wasted lots of time on it. + */ + syslog(LOG_WARNING, + "no reply to SETTIME from %s", htp->name); + if (++htp->noanswer >= LOSTHOST) { + if (trace) { + fprintf(fd, + "purging %s for not answering", + htp->name); + (void)fflush(fd); + } + htp = remmach(htp); + } + } + } +} + +void +prthp(delta) + clock_t delta; +{ + static time_t next_time; + time_t this_time; + struct tms tm; + struct hosttbl *htp; + int length, l; + int i; + + if (!fd) /* quit if tracing already off */ + return; + + this_time = times(&tm); + if (this_time + delta < next_time) + return; + next_time = this_time + CLK_TCK; + + fprintf(fd, "host table: %d entries at %s\n", slvcount, date()); + htp = self.l_fwd; + length = 1; + for (i = 1; i <= slvcount; i++, htp = htp->l_fwd) { + l = strlen(htp->name) + 1; + if (length+l >= 80) { + fprintf(fd, "\n"); + length = 0; + } + length += l; + fprintf(fd, " %s", htp->name); + } + fprintf(fd, "\n"); +} + + +static struct hosttbl *newhost_hash; +static struct hosttbl *lasthfree = &hosttbl[0]; + + +struct hosttbl * /* answer or 0 */ +findhost(name) + char *name; +{ + int i, j; + struct hosttbl *htp; + char *p; + + j= 0; + for (p = name, i = 0; i < 8 && *p != '\0'; i++, p++) + j = (j << 2) ^ *p; + newhost_hash = &hosttbl[j % NHOSTS]; + + htp = newhost_hash; + if (htp->name[0] == '\0') + return(0); + do { + if (!strcmp(name, htp->name)) + return(htp); + htp = htp->h_fwd; + } while (htp != newhost_hash); + return(0); +} + +/* + * add a host to the list of controlled machines if not already there + */ +struct hosttbl * +addmach(name, addr, ntp) + char *name; + struct sockaddr_in *addr; + struct netinfo *ntp; +{ + struct hosttbl *ret, *p, *b, *f; + + ret = findhost(name); + if (ret == 0) { + if (slvcount >= NHOSTS) { + if (trace) { + fprintf(fd, "no more slots in host table\n"); + prthp(CLK_TCK); + } + syslog(LOG_ERR, "no more slots in host table"); + Mflag = 0; + longjmp(jmpenv, 2); /* give up and be a slave */ + } + + /* if our home hash slot is occupied, find a free entry + * in the hash table + */ + if (newhost_hash->name[0] != '\0') { + do { + ret = lasthfree; + if (++lasthfree > &hosttbl[NHOSTS]) + lasthfree = &hosttbl[1]; + } while (ret->name[0] != '\0'); + + if (!newhost_hash->head) { + /* Move an interloper using our home. Use + * scratch pointers in case the new head is + * pointing to itself. + */ + f = newhost_hash->h_fwd; + b = newhost_hash->h_bak; + f->h_bak = ret; + b->h_fwd = ret; + f = newhost_hash->l_fwd; + b = newhost_hash->l_bak; + f->l_bak = ret; + b->l_fwd = ret; + bcopy(newhost_hash,ret,sizeof(*ret)); + ret = newhost_hash; + ret->head = 1; + ret->h_fwd = ret; + ret->h_bak = ret; + } else { + /* link to an existing chain in our home + */ + ret->head = 0; + p = newhost_hash->h_bak; + ret->h_fwd = newhost_hash; + ret->h_bak = p; + p->h_fwd = ret; + newhost_hash->h_bak = ret; + } + } else { + ret = newhost_hash; + ret->head = 1; + ret->h_fwd = ret; + ret->h_bak = ret; + } + ret->addr = *addr; + ret->ntp = ntp; + (void)strncpy(ret->name, name, sizeof(ret->name)); + ret->good = good_host_name(name); + ret->l_fwd = &self; + ret->l_bak = self.l_bak; + self.l_bak->l_fwd = ret; + self.l_bak = ret; + slvcount++; + + ret->noanswer = 0; + ret->need_set = 1; + + } else { + ret->noanswer = (ret->noanswer != 0); + } + + /* need to clear sequence number anyhow */ + ret->seq = 0; + return(ret); +} + +/* + * remove the machine with the given index in the host table. + */ +struct hosttbl * +remmach(htp) + struct hosttbl *htp; +{ + struct hosttbl *lprv, *hnxt, *f, *b; + + if (trace) + fprintf(fd, "remove %s\n", htp->name); + + /* get out of the lists */ + htp->l_fwd->l_bak = lprv = htp->l_bak; + htp->l_bak->l_fwd = htp->l_fwd; + htp->h_fwd->h_bak = htp->h_bak; + htp->h_bak->h_fwd = hnxt = htp->h_fwd; + + /* If we are in the home slot, pull up the chain */ + if (htp->head && hnxt != htp) { + if (lprv == hnxt) + lprv = htp; + + /* Use scratch pointers in case the new head is pointing to + * itself. + */ + f = hnxt->h_fwd; + b = hnxt->h_bak; + f->h_bak = htp; + b->h_fwd = htp; + f = hnxt->l_fwd; + b = hnxt->l_bak; + f->l_bak = htp; + b->l_fwd = htp; + hnxt->head = 1; + bcopy(hnxt, htp, sizeof(*htp)); + lasthfree = hnxt; + } else { + lasthfree = htp; + } + + lasthfree->name[0] = '\0'; + lasthfree->h_fwd = 0; + lasthfree->l_fwd = 0; + slvcount--; + + return lprv; +} + + +/* + * Remove all the machines from the host table that exist on the given + * network. This is called when a master transitions to a slave on a + * given network. + */ +void +rmnetmachs(ntp) + struct netinfo *ntp; +{ + struct hosttbl *htp; + + if (trace) + prthp(CLK_TCK); + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + if (ntp == htp->ntp) + htp = remmach(htp); + } + if (trace) + prthp(CLK_TCK); +} + +void +masterup(net) + struct netinfo *net; +{ + xmit(TSP_MASTERUP, 0, &net->dest_addr); + + /* + * Do not tell new slaves our time for a while. This ensures + * we do not tell them to start using our time, before we have + * found a good master. + */ + (void)gettimeofday(&net->slvwait, 0); +} + +void +newslave(msg) + struct tsp *msg; +{ + struct hosttbl *htp; + struct tsp *answer, to; + struct timeval now; + + if (!fromnet || fromnet->status != MASTER) + return; + + htp = addmach(msg->tsp_name, &from,fromnet); + htp->seq = msg->tsp_seq; + if (trace) + prthp(0); + + /* + * If we are stable, send our time to the slave. + * Do not go crazy if the date has been changed. + */ + (void)gettimeofday(&now, 0); + if (now.tv_sec >= fromnet->slvwait.tv_sec+3 + || now.tv_sec < fromnet->slvwait.tv_sec) { + to.tsp_type = TSP_SETTIME; + (void)strcpy(to.tsp_name, hostname); + (void)gettimeofday(&to.tsp_time, 0); + answer = acksend(&to, &htp->addr, + htp->name, TSP_ACK, + 0, htp->noanswer); + if (answer) { + htp->need_set = 0; + } else { + syslog(LOG_WARNING, + "no reply to initial SETTIME from %s", + htp->name); + htp->noanswer = LOSTHOST; + } + } +} + + +/* + * react to a TSP_QUIT: + */ +void +doquit(msg) + struct tsp *msg; +{ + if (fromnet->status == MASTER) { + if (!good_host_name(msg->tsp_name)) { + if (fromnet->quit_count <= 0) { + syslog(LOG_NOTICE,"untrusted %s told us QUIT", + msg->tsp_name); + suppress(&from, msg->tsp_name, fromnet); + fromnet->quit_count = 1; + return; + } + syslog(LOG_NOTICE, "untrusted %s told us QUIT twice", + msg->tsp_name); + fromnet->quit_count = 2; + fromnet->status = NOMASTER; + } else { + fromnet->status = SLAVE; + } + rmnetmachs(fromnet); + longjmp(jmpenv, 2); /* give up and be a slave */ + + } else { + if (!good_host_name(msg->tsp_name)) { + syslog(LOG_NOTICE, "untrusted %s told us QUIT", + msg->tsp_name); + fromnet->quit_count = 2; + } + } +} + +void +traceon() +{ + if (!fd) { + fd = fopen(_PATH_TIMEDLOG, "w"); + if (!fd) { + trace = 0; + return; + } + fprintf(fd,"Tracing started at %s\n", date()); + } + trace = 1; + get_goodgroup(1); + setstatus(); + prthp(CLK_TCK); +} + + +void +traceoff(msg) + char *msg; +{ + get_goodgroup(1); + setstatus(); + prthp(CLK_TCK); + if (trace) { + fprintf(fd, msg, date()); + (void)fclose(fd); + fd = 0; + } +#ifdef GPROF + moncontrol(0); + _mcleanup(); + moncontrol(1); +#endif + trace = OFF; +} + + +#ifdef sgi +void +logwtmp(otime, ntime) + struct timeval *otime, *ntime; +{ + static struct utmp wtmp[2] = { + {"","",OTIME_MSG,0,OLD_TIME,0,0,0}, + {"","",NTIME_MSG,0,NEW_TIME,0,0,0} + }; + static char *wtmpfile = WTMP_FILE; + int f; + + wtmp[0].ut_time = otime->tv_sec + (otime->tv_usec + 500000) / 1000000; + wtmp[1].ut_time = ntime->tv_sec + (ntime->tv_usec + 500000) / 1000000; + if (wtmp[0].ut_time == wtmp[1].ut_time) + return; + + setutent(); + (void)pututline(&wtmp[0]); + (void)pututline(&wtmp[1]); + endutent(); + if ((f = open(wtmpfile, O_WRONLY|O_APPEND)) >= 0) { + (void) write(f, (char *)wtmp, sizeof(wtmp)); + (void) close(f); + } +} +#endif /* sgi */ diff --git a/timed.tproj/timed.tproj/measure.c b/timed.tproj/timed.tproj/measure.c new file mode 100644 index 0000000..6b809b2 --- /dev/null +++ b/timed.tproj/timed.tproj/measure.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)measure.c 8.2 (Berkeley) 3/26/95"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" +#include +#include +#include + +#define MSEC_DAY (SECDAY*1000) + +#define PACKET_IN 1024 + +#define MSGS 5 /* timestamps to average */ +#define TRIALS 10 /* max # of timestamps sent */ + +extern int sock_raw; + +int measure_delta; + +static n_short seqno = 0; + +/* + * Measures the differences between machines' clocks using + * ICMP timestamp messages. + */ +int /* status val defined in globals.h */ +measure(maxmsec, wmsec, hname, addr, print) + u_long maxmsec; /* wait this many msec at most */ + u_long wmsec; /* msec to wait for an answer */ + char *hname; + struct sockaddr_in *addr; + int print; /* print complaints on stderr */ +{ + int length; + int measure_status; + int rcvcount, trials; + int cc, count; + fd_set ready; + long sendtime, recvtime, histime1, histime2; + long idelta, odelta, total; + long min_idelta, min_odelta; + struct timeval tdone, tcur, ttrans, twait, tout; + u_char packet[PACKET_IN], opacket[64]; + register struct icmp *icp = (struct icmp *) packet; + register struct icmp *oicp = (struct icmp *) opacket; + struct ip *ip = (struct ip *) packet; + + min_idelta = min_odelta = 0x7fffffff; + measure_status = HOSTDOWN; + measure_delta = HOSTDOWN; + errno = 0; + + /* open raw socket used to measure time differences */ + if (sock_raw < 0) { + sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sock_raw < 0) { + syslog(LOG_ERR, "opening raw socket: %m"); + goto quit; + } + } + + + /* + * empty the icmp input queue + */ + FD_ZERO(&ready); + for (;;) { + tout.tv_sec = tout.tv_usec = 0; + FD_SET(sock_raw, &ready); + if (select(sock_raw+1, &ready, 0,0, &tout)) { + length = sizeof(struct sockaddr_in); + cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, + 0,&length); + if (cc < 0) + goto quit; + continue; + } + break; + } + + /* + * Choose the smallest transmission time in each of the two + * directions. Use these two latter quantities to compute the delta + * between the two clocks. + */ + + oicp->icmp_type = ICMP_TSTAMP; + oicp->icmp_code = 0; + oicp->icmp_id = getpid(); + oicp->icmp_rtime = 0; + oicp->icmp_ttime = 0; + oicp->icmp_seq = seqno; + + FD_ZERO(&ready); + +#ifdef sgi + sginap(1); /* start at a clock tick */ +#endif /* sgi */ + + (void)gettimeofday(&tdone, 0); + mstotvround(&tout, maxmsec); + timevaladd(&tdone, &tout); /* when we give up */ + + mstotvround(&twait, wmsec); + + rcvcount = 0; + trials = 0; + while (rcvcount < MSGS) { + (void)gettimeofday(&tcur, 0); + + /* + * keep sending until we have sent the max + */ + if (trials < TRIALS) { + trials++; + oicp->icmp_otime = htonl((tcur.tv_sec % SECDAY) * 1000 + + tcur.tv_usec / 1000); + oicp->icmp_cksum = 0; + oicp->icmp_cksum = in_cksum((u_short*)oicp, + sizeof(*oicp)); + + count = sendto(sock_raw, opacket, sizeof(*oicp), 0, + (struct sockaddr*)addr, + sizeof(struct sockaddr)); + if (count < 0) { + if (measure_status == HOSTDOWN) + measure_status = UNREACHABLE; + goto quit; + } + ++oicp->icmp_seq; + + ttrans = tcur; + timevaladd(&ttrans, &twait); + } else { + ttrans = tdone; + } + + while (rcvcount < trials) { + timevalsub(&tout, &ttrans, &tcur); + if (tout.tv_sec < 0) + tout.tv_sec = 0; + + FD_SET(sock_raw, &ready); + count = select(sock_raw+1, &ready, (fd_set *)0, + (fd_set *)0, &tout); + (void)gettimeofday(&tcur, (struct timezone *)0); + if (count <= 0) + break; + + length = sizeof(struct sockaddr_in); + cc = recvfrom(sock_raw, (char *)packet, PACKET_IN, 0, + 0,&length); + if (cc < 0) + goto quit; + + /* + * got something. See if it is ours + */ + icp = (struct icmp *)(packet + (ip->ip_hl << 2)); + if (cc < sizeof(*ip) + || icp->icmp_type != ICMP_TSTAMPREPLY + || icp->icmp_id != oicp->icmp_id + || icp->icmp_seq < seqno + || icp->icmp_seq >= oicp->icmp_seq) + continue; + + + sendtime = ntohl(icp->icmp_otime); + recvtime = ((tcur.tv_sec % SECDAY) * 1000 + + tcur.tv_usec / 1000); + + total = recvtime-sendtime; + if (total < 0) /* do not hassle midnight */ + continue; + + rcvcount++; + histime1 = ntohl(icp->icmp_rtime); + histime2 = ntohl(icp->icmp_ttime); + /* + * a host using a time format different from + * msec. since midnight UT (as per RFC792) should + * set the high order bit of the 32-bit time + * value it transmits. + */ + if ((histime1 & 0x80000000) != 0) { + measure_status = NONSTDTIME; + goto quit; + } + measure_status = GOOD; + + idelta = recvtime-histime2; + odelta = histime1-sendtime; + + /* do not be confused by midnight */ + if (idelta < -MSEC_DAY/2) idelta += MSEC_DAY; + else if (idelta > MSEC_DAY/2) idelta -= MSEC_DAY; + + if (odelta < -MSEC_DAY/2) odelta += MSEC_DAY; + else if (odelta > MSEC_DAY/2) odelta -= MSEC_DAY; + + /* save the quantization error so that we can get a + * measurement finer than our system clock. + */ + if (total < MIN_ROUND) { + measure_delta = (odelta - idelta)/2; + goto quit; + } + + if (idelta < min_idelta) + min_idelta = idelta; + if (odelta < min_odelta) + min_odelta = odelta; + + measure_delta = (min_odelta - min_idelta)/2; + } + + if (tcur.tv_sec > tdone.tv_sec + || (tcur.tv_sec == tdone.tv_sec + && tcur.tv_usec >= tdone.tv_usec)) + break; + } + +quit: + seqno += TRIALS; /* allocate our sequence numbers */ + + /* + * If no answer is received for TRIALS consecutive times, + * the machine is assumed to be down + */ + if (measure_status == GOOD) { + if (trace) { + fprintf(fd, + "measured delta %4d, %d trials to %-15s %s\n", + measure_delta, trials, + inet_ntoa(addr->sin_addr), hname); + } + } else if (print) { + if (errno != 0) + fprintf(stderr, "measure %s: %s\n", hname, + strerror(errno)); + } else { + if (errno != 0) { + syslog(LOG_ERR, "measure %s: %m", hname); + } else { + syslog(LOG_ERR, "measure: %s did not respond", hname); + } + if (trace) { + fprintf(fd, + "measure: %s failed after %d trials\n", + hname, trials); + (void)fflush(fd); + } + } + + return(measure_status); +} + + + + + +/* + * round a number of milliseconds into a struct timeval + */ +void +mstotvround(res, x) + struct timeval *res; + long x; +{ +#ifndef sgi + if (x < 0) + x = -((-x + 3)/5); + else + x = (x+3)/5; + x *= 5; +#endif /* sgi */ + res->tv_sec = x/1000; + res->tv_usec = (x-res->tv_sec*1000)*1000; + if (res->tv_usec < 0) { + res->tv_usec += 1000000; + res->tv_sec--; + } +} + +void +timevaladd(tv1, tv2) + struct timeval *tv1, *tv2; +{ + tv1->tv_sec += tv2->tv_sec; + tv1->tv_usec += tv2->tv_usec; + if (tv1->tv_usec >= 1000000) { + tv1->tv_sec++; + tv1->tv_usec -= 1000000; + } + if (tv1->tv_usec < 0) { + tv1->tv_sec--; + tv1->tv_usec += 1000000; + } +} + +void +timevalsub(res, tv1, tv2) + struct timeval *res, *tv1, *tv2; +{ + res->tv_sec = tv1->tv_sec - tv2->tv_sec; + res->tv_usec = tv1->tv_usec - tv2->tv_usec; + if (res->tv_usec >= 1000000) { + res->tv_sec++; + res->tv_usec -= 1000000; + } + if (res->tv_usec < 0) { + res->tv_sec--; + res->tv_usec += 1000000; + } +} diff --git a/timed.tproj/timed.tproj/networkdelta.c b/timed.tproj/timed.tproj/networkdelta.c new file mode 100644 index 0000000..51576f6 --- /dev/null +++ b/timed.tproj/timed.tproj/networkdelta.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)networkdelta.c 8.3 (Berkeley) 4/27/95"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" + +static long median __P((double, float *, long *, long *, unsigned int)); + +/* + * Compute a corrected date. + * Compute the median of the reasonable differences. First compute + * the median of all authorized differences, and then compute the + * median of all differences that are reasonably close to the first + * median. + * + * This differs from the original BSD implementation, which looked for + * the largest group of machines with essentially the same date. + * That assumed that machines with bad clocks would be uniformly + * distributed. Unfortunately, in real life networks, the distribution + * of machines is not uniform among models of machines, and the + * distribution of errors in clocks tends to be quite consistent + * for a given model. In other words, all model VI Supre Servres + * from GoFast Inc. tend to have about the same error. + * The original BSD implementation would chose the clock of the + * most common model, and discard all others. + * + * Therefore, get best we can do is to try to average over all + * of the machines in the network, while discarding "obviously" + * bad values. + */ +long +networkdelta() +{ + struct hosttbl *htp; + long med; + long lodelta, hidelta; + long logood, higood; + long x[NHOSTS]; + long *xp; + int numdelta; + float eps; + + /* + * compute the median of the good values + */ + med = 0; + numdelta = 1; + xp = &x[0]; + *xp = 0; /* account for ourself */ + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + if (htp->good + && htp->noanswer == 0 + && htp->delta != HOSTDOWN) { + med += htp->delta; + numdelta++; + *++xp = htp->delta; + } + } + + /* + * If we are the only trusted time keeper, then do not change our + * clock. There may be another time keeping service active. + */ + if (numdelta == 1) + return 0; + + /* get average of trusted values */ + med /= numdelta; + + if (trace) + fprintf(fd, "median of %d values starting at %ld is about ", + numdelta, med); + /* get median of all trusted values, using average as initial guess */ + eps = med - x[0]; + med = median(med, &eps, &x[0], xp+1, VALID_RANGE); + + /* Compute the median of all good values. + * Good values are those of all clocks, including untrusted clocks, + * that are + * - trusted and somewhat close to the median of the + * trusted clocks + * - trusted or untrusted and very close to the median of the + * trusted clocks + */ + hidelta = med + GOOD_RANGE; + lodelta = med - GOOD_RANGE; + higood = med + VGOOD_RANGE; + logood = med - VGOOD_RANGE; + xp = &x[0]; + htp = &self; + do { + if (htp->noanswer == 0 + && htp->delta >= lodelta + && htp->delta <= hidelta + && (htp->good + || (htp->delta >= logood + && htp->delta <= higood))) { + *xp++ = htp->delta; + } + } while (&self != (htp = htp->l_fwd)); + + if (xp == &x[0]) { + if (trace) + fprintf(fd, "nothing close to median %ld\n", med); + return med; + } + + if (xp == &x[1]) { + if (trace) + fprintf(fd, "only value near median is %ld\n", x[0]); + return x[0]; + } + + if (trace) + fprintf(fd, "median of %d values starting at %ld is ", + xp-&x[0], med); + return median(med, &eps, &x[0], xp, 1); +} + + +/* + * compute the median of an array of signed integers, using the idea + * in <>. + */ +static long +median(a0, eps_ptr, x, xlim, gnuf) + double a0; /* initial guess for the median */ + float *eps_ptr; /* spacing near the median */ + long *x, *xlim; /* the data */ + unsigned int gnuf; /* good enough estimate */ +{ + long *xptr; + float a = a0; + float ap = LONG_MAX; /* bounds on the median */ + float am = -LONG_MAX; + float aa; + int npts; /* # of points above & below guess */ + float xp; /* closet point above the guess */ + float xm; /* closet point below the guess */ + float eps; + float dum, sum, sumx; + int pass; +#define AMP 1.5 /* smoothing constants */ +#define AFAC 1.5 + + eps = *eps_ptr; + if (eps < 1.0) { + eps = -eps; + if (eps < 1.0) + eps = 1.0; + } + + for (pass = 1; ; pass++) { /* loop over the data */ + sum = 0.0; + sumx = 0.0; + npts = 0; + xp = LONG_MAX; + xm = -LONG_MAX; + + for (xptr = x; xptr != xlim; xptr++) { + float xx = *xptr; + + dum = xx - a; + if (dum != 0.0) { /* avoid dividing by 0 */ + if (dum > 0.0) { + npts++; + if (xx < xp) + xp = xx; + } else { + npts--; + if (xx > xm) + xm = xx; + dum = -dum; + } + dum = 1.0/(eps + dum); + sum += dum; + sumx += xx * dum; + } + } + + if (ap-am < gnuf || sum == 0) { + if (trace) + fprintf(fd, + "%ld in %d passes;" + " early out balance=%d\n", + (long)a, pass, npts); + return a; /* guess was good enough */ + } + + aa = (sumx/sum-a)*AMP; + if (npts >= 2) { /* guess was too low */ + am = a; + aa = xp + max(0.0, aa); + if (aa >= ap) + aa = (a + ap)/2; + + } else if (npts <= -2) { /* guess was two high */ + ap = a; + aa = xm + min(0.0, aa); + if (aa <= am) + aa = (a + am)/2; + + } else { + break; /* got it */ + } + + if (a == aa) { + if (trace) + fprintf(fd, "%ld in %d passes;" + " force out balance=%d\n", + (long)a, pass, npts); + return a; + } + eps = AFAC*abs(aa - a); + *eps_ptr = eps; + a = aa; + } + + if (((x - xlim) % 2) != 0) { /* even number of points? */ + if (npts == 0) /* yes, return an average */ + a = (xp+xm)/2; + else if (npts > 0) + a = (a+xp)/2; + else + a = (xm+a)/2; + + } else if (npts != 0) { /* odd number of points */ + if (npts > 0) + a = xp; + else + a = xm; + } + + if (trace) + fprintf(fd, "%ld in %d passes\n", (long)a, pass); + return a; +} diff --git a/timed.tproj/timed.tproj/pathnames.h b/timed.tproj/timed.tproj/pathnames.h new file mode 100644 index 0000000..1a3faf3 --- /dev/null +++ b/timed.tproj/timed.tproj/pathnames.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/6/93 + */ + +#include + +#ifdef sgi +#define _PATH_MASTERLOG "/usr/adm/timed.masterlog" +#define _PATH_TIMEDLOG "/usr/adm/timed.log" +#else +#define _PATH_MASTERLOG "/var/log/timed.masterlog" +#define _PATH_TIMEDLOG "/var/log/timed.log" +#endif diff --git a/timed.tproj/timed.tproj/readmsg.c b/timed.tproj/timed.tproj/readmsg.c new file mode 100644 index 0000000..fab1e77 --- /dev/null +++ b/timed.tproj/timed.tproj/readmsg.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)readmsg.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" + +extern char *tsptype[]; + +/* + * LOOKAT checks if the message is of the requested type and comes from + * the right machine, returning 1 in case of affirmative answer + */ +#define LOOKAT(msg, mtype, mfrom, netp, froms) \ + (((mtype) == TSP_ANY || (mtype) == (msg).tsp_type) && \ + ((mfrom) == 0 || !strcmp((mfrom), (msg).tsp_name)) && \ + ((netp) == 0 || \ + ((netp)->mask & (froms).sin_addr.s_addr) == (netp)->net.s_addr)) + +struct timeval rtime, rwait, rtout; +struct tsp msgin; +static struct tsplist { + struct tsp info; + struct timeval when; + struct sockaddr_in addr; + struct tsplist *p; +} msgslist; +struct sockaddr_in from; +struct netinfo *fromnet; +struct timeval from_when; + +/* + * `readmsg' returns message `type' sent by `machfrom' if it finds it + * either in the receive queue, or in a linked list of previously received + * messages that it maintains. + * Otherwise it waits to see if the appropriate message arrives within + * `intvl' seconds. If not, it returns NULL. + */ + +struct tsp * +readmsg(type, machfrom, intvl, netfrom) + int type; + char *machfrom; + struct timeval *intvl; + struct netinfo *netfrom; +{ + int length; + fd_set ready; + static struct tsplist *head = &msgslist; + static struct tsplist *tail = &msgslist; + static int msgcnt = 0; + struct tsplist *prev; + register struct netinfo *ntp; + register struct tsplist *ptr; + + if (trace) { + fprintf(fd, "readmsg: looking for %s from %s, %s\n", + tsptype[type], machfrom == NULL ? "ANY" : machfrom, + netfrom == NULL ? "ANYNET" : inet_ntoa(netfrom->net)); + if (head->p != 0) { + length = 1; + for (ptr = head->p; ptr != 0; ptr = ptr->p) { + /* do not repeat the hundreds of messages */ + if (++length > 3) { + if (ptr == tail) { + fprintf(fd,"\t ...%d skipped\n", + length); + } else { + continue; + } + } + fprintf(fd, length > 1 ? "\t" : "queue:\t"); + print(&ptr->info, &ptr->addr); + } + } + } + + ptr = head->p; + prev = head; + + /* + * Look for the requested message scanning through the + * linked list. If found, return it and free the space + */ + + while (ptr != NULL) { + if (LOOKAT(ptr->info, type, machfrom, netfrom, ptr->addr)) { +again: + msgin = ptr->info; + from = ptr->addr; + from_when = ptr->when; + prev->p = ptr->p; + if (ptr == tail) + tail = prev; + free((char *)ptr); + fromnet = NULL; + if (netfrom == NULL) + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if ((ntp->mask & from.sin_addr.s_addr) == + ntp->net.s_addr) { + fromnet = ntp; + break; + } + } + else + fromnet = netfrom; + if (trace) { + fprintf(fd, "readmsg: found "); + print(&msgin, &from); + } + +/* The protocol can get far behind. When it does, it gets + * hopelessly confused. So delete duplicate messages. + */ + for (ptr = prev; (ptr = ptr->p) != NULL; prev = ptr) { + if (ptr->addr.sin_addr.s_addr + == from.sin_addr.s_addr + && ptr->info.tsp_type == msgin.tsp_type) { + if (trace) + fprintf(fd, "\tdup "); + goto again; + } + } + msgcnt--; + return(&msgin); + } else { + prev = ptr; + ptr = ptr->p; + } + } + + /* + * If the message was not in the linked list, it may still be + * coming from the network. Set the timer and wait + * on a select to read the next incoming message: if it is the + * right one, return it, otherwise insert it in the linked list. + */ + + (void)gettimeofday(&rtout, 0); + timevaladd(&rtout, intvl); + FD_ZERO(&ready); + for (;;) { + (void)gettimeofday(&rtime, 0); + timevalsub(&rwait, &rtout, &rtime); + if (rwait.tv_sec < 0) + rwait.tv_sec = rwait.tv_usec = 0; + else if (rwait.tv_sec == 0 + && rwait.tv_usec < 1000000/CLK_TCK) + rwait.tv_usec = 1000000/CLK_TCK; + + if (trace) { + fprintf(fd, "readmsg: wait %ld.%6ld at %s\n", + rwait.tv_sec, rwait.tv_usec, date()); + /* Notice a full disk, as we flush trace info. + * It is better to flush periodically than at + * every line because the tracing consists of bursts + * of many lines. Without care, tracing slows + * down the code enough to break the protocol. + */ + if (rwait.tv_sec != 0 + && EOF == fflush(fd)) + traceoff("Tracing ended for cause at %s\n"); + } + + FD_SET(sock, &ready); + if (!select(sock+1, &ready, (fd_set *)0, (fd_set *)0, + &rwait)) { + if (rwait.tv_sec == 0 && rwait.tv_usec == 0) + return(0); + continue; + } + length = sizeof(from); + if (recvfrom(sock, (char *)&msgin, sizeof(struct tsp), 0, + (struct sockaddr*)&from, &length) < 0) { + syslog(LOG_ERR, "recvfrom: %m"); + exit(1); + } + (void)gettimeofday(&from_when, (struct timezone *)0); + bytehostorder(&msgin); + + if (msgin.tsp_vers > TSPVERSION) { + if (trace) { + fprintf(fd,"readmsg: version mismatch\n"); + /* should do a dump of the packet */ + } + continue; + } + + fromnet = NULL; + for (ntp = nettab; ntp != NULL; ntp = ntp->next) + if ((ntp->mask & from.sin_addr.s_addr) == + ntp->net.s_addr) { + fromnet = ntp; + break; + } + + /* + * drop packets from nets we are ignoring permanently + */ + if (fromnet == NULL) { + /* + * The following messages may originate on + * this host with an ignored network address + */ + if (msgin.tsp_type != TSP_TRACEON && + msgin.tsp_type != TSP_SETDATE && + msgin.tsp_type != TSP_MSITE && + msgin.tsp_type != TSP_TEST && + msgin.tsp_type != TSP_TRACEOFF) { + if (trace) { + fprintf(fd,"readmsg: discard null net "); + print(&msgin, &from); + } + continue; + } + } + + /* + * Throw away messages coming from this machine, + * unless they are of some particular type. + * This gets rid of broadcast messages and reduces + * master processing time. + */ + if (!strcmp(msgin.tsp_name, hostname) + && msgin.tsp_type != TSP_SETDATE + && msgin.tsp_type != TSP_TEST + && msgin.tsp_type != TSP_MSITE + && msgin.tsp_type != TSP_TRACEON + && msgin.tsp_type != TSP_TRACEOFF + && msgin.tsp_type != TSP_LOOP) { + if (trace) { + fprintf(fd, "readmsg: discard own "); + print(&msgin, &from); + } + continue; + } + + /* + * Send acknowledgements here; this is faster and + * avoids deadlocks that would occur if acks were + * sent from a higher level routine. Different + * acknowledgements are necessary, depending on + * status. + */ + if (fromnet == NULL) /* do not de-reference 0 */ + ignoreack(); + else if (fromnet->status == MASTER) + masterack(); + else if (fromnet->status == SLAVE) + slaveack(); + else + ignoreack(); + + if (LOOKAT(msgin, type, machfrom, netfrom, from)) { + if (trace) { + fprintf(fd, "readmsg: "); + print(&msgin, &from); + } + return(&msgin); + } else if (++msgcnt > NHOSTS*3) { + +/* The protocol gets hopelessly confused if it gets too far +* behind. However, it seems able to recover from all cases of lost +* packets. Therefore, if we are swamped, throw everything away. +*/ + if (trace) + fprintf(fd, + "readmsg: discarding %d msgs\n", + msgcnt); + msgcnt = 0; + while ((ptr=head->p) != NULL) { + head->p = ptr->p; + free((char *)ptr); + } + tail = head; + } else { + tail->p = (struct tsplist *) + malloc(sizeof(struct tsplist)); + tail = tail->p; + tail->p = NULL; + tail->info = msgin; + tail->addr = from; + /* timestamp msgs so SETTIMEs are correct */ + tail->when = from_when; + } + } +} + +/* + * Send the necessary acknowledgements: + * only the type ACK is to be sent by a slave + */ +void +slaveack() +{ + switch(msgin.tsp_type) { + + case TSP_ADJTIME: + case TSP_SETTIME: + case TSP_ACCEPT: + case TSP_REFUSE: + case TSP_TRACEON: + case TSP_TRACEOFF: + case TSP_QUIT: + if (trace) { + fprintf(fd, "Slaveack: "); + print(&msgin, &from); + } + xmit(TSP_ACK,msgin.tsp_seq, &from); + break; + + default: + if (trace) { + fprintf(fd, "Slaveack: no ack: "); + print(&msgin, &from); + } + break; + } +} + +/* + * Certain packets may arrive from this machine on ignored networks. + * These packets should be acknowledged. + */ +void +ignoreack() +{ + switch(msgin.tsp_type) { + + case TSP_TRACEON: + case TSP_TRACEOFF: + case TSP_QUIT: + if (trace) { + fprintf(fd, "Ignoreack: "); + print(&msgin, &from); + } + xmit(TSP_ACK,msgin.tsp_seq, &from); + break; + + default: + if (trace) { + fprintf(fd, "Ignoreack: no ack: "); + print(&msgin, &from); + } + break; + } +} + +/* + * `masterack' sends the necessary acknowledgments + * to the messages received by a master + */ +void +masterack() +{ + struct tsp resp; + + resp = msgin; + resp.tsp_vers = TSPVERSION; + (void)strcpy(resp.tsp_name, hostname); + + switch(msgin.tsp_type) { + + case TSP_QUIT: + case TSP_TRACEON: + case TSP_TRACEOFF: + case TSP_MSITEREQ: + if (trace) { + fprintf(fd, "Masterack: "); + print(&msgin, &from); + } + xmit(TSP_ACK,msgin.tsp_seq, &from); + break; + + case TSP_RESOLVE: + case TSP_MASTERREQ: + if (trace) { + fprintf(fd, "Masterack: "); + print(&msgin, &from); + } + xmit(TSP_MASTERACK,msgin.tsp_seq, &from); + break; + + default: + if (trace) { + fprintf(fd,"Masterack: no ack: "); + print(&msgin, &from); + } + break; + } +} + +/* + * Print a TSP message + */ +void +print(msg, addr) + struct tsp *msg; + struct sockaddr_in *addr; +{ + char tm[26]; + switch (msg->tsp_type) { + + case TSP_LOOP: + fprintf(fd, "%s %d %-6u #%d %-15s %s\n", + tsptype[msg->tsp_type], + msg->tsp_vers, + msg->tsp_seq, + msg->tsp_hopcnt, + inet_ntoa(addr->sin_addr), + msg->tsp_name); + break; + + case TSP_SETTIME: + case TSP_SETDATE: + case TSP_SETDATEREQ: +#ifdef sgi + (void)cftime(tm, "%D %T", &msg->tsp_time.tv_sec); +#else + strncpy(tm, ctime(&msg->tsp_time.tv_sec)+3+1, sizeof(tm)); + tm[15] = '\0'; /* ugh */ +#endif /* sgi */ + fprintf(fd, "%s %d %-6u %s %-15s %s\n", + tsptype[msg->tsp_type], + msg->tsp_vers, + msg->tsp_seq, + tm, + inet_ntoa(addr->sin_addr), + msg->tsp_name); + break; + + case TSP_ADJTIME: + fprintf(fd, "%s %d %-6u (%ld,%ld) %-15s %s\n", + tsptype[msg->tsp_type], + msg->tsp_vers, + msg->tsp_seq, + msg->tsp_time.tv_sec, + msg->tsp_time.tv_usec, + inet_ntoa(addr->sin_addr), + msg->tsp_name); + break; + + default: + fprintf(fd, "%s %d %-6u %-15s %s\n", + tsptype[msg->tsp_type], + msg->tsp_vers, + msg->tsp_seq, + inet_ntoa(addr->sin_addr), + msg->tsp_name); + break; + } +} diff --git a/timed.tproj/timed.tproj/slave.c b/timed.tproj/timed.tproj/slave.c new file mode 100644 index 0000000..0b72058 --- /dev/null +++ b/timed.tproj/timed.tproj/slave.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)slave.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "globals.h" +#include +#include "pathnames.h" + +extern jmp_buf jmpenv; +extern int Mflag; +extern int justquit; + +extern u_short sequence; + +static char master_name[MAXHOSTNAMELEN+1]; +static struct netinfo *old_slavenet; +static int old_status; + +static void schgdate __P((struct tsp *, char *)); +static void setmaster __P((struct tsp *)); +static void answerdelay __P((void)); + +#ifdef sgi +extern void logwtmp __P((struct timeval *, struct timeval *)); +#else +extern void logwtmp __P((char *, char *, char *)); +#endif /* sgi */ + +int +slave() +{ + int tries; + long electiontime, refusetime, looktime, looptime, adjtime; + u_short seq; + long fastelection; +#define FASTTOUT 3 + struct in_addr cadr; + struct timeval otime; + struct sockaddr_in taddr; + char tname[MAXHOSTNAMELEN]; + struct tsp *msg, to; + struct timeval ntime, wait; + struct tsp *answer; + int timeout(); + char olddate[32]; + char newdate[32]; + struct netinfo *ntp; + struct hosttbl *htp; + + + old_slavenet = 0; + seq = 0; + refusetime = 0; + adjtime = 0; + + (void)gettimeofday(&ntime, 0); + electiontime = ntime.tv_sec + delay2; + fastelection = ntime.tv_sec + FASTTOUT; + if (justquit) + looktime = electiontime; + else + looktime = fastelection; + looptime = fastelection; + + if (slavenet) + xmit(TSP_SLAVEUP, 0, &slavenet->dest_addr); + if (status & MASTER) { + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == MASTER) + masterup(ntp); + } + } + +loop: + get_goodgroup(0); + (void)gettimeofday(&ntime, (struct timezone *)0); + if (ntime.tv_sec > electiontime) { + if (trace) + fprintf(fd, "election timer expired\n"); + longjmp(jmpenv, 1); + } + + if (ntime.tv_sec >= looktime) { + if (trace) + fprintf(fd, "Looking for nets to master\n"); + + if (Mflag && nignorednets > 0) { + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == IGNORE + || ntp->status == NOMASTER) { + lookformaster(ntp); + if (ntp->status == MASTER) { + masterup(ntp); + } else if (ntp->status == MASTER) { + ntp->status = NOMASTER; + } + } + if (ntp->status == MASTER + && --ntp->quit_count < 0) + ntp->quit_count = 0; + } + makeslave(slavenet); /* prune extras */ + setstatus(); + } + (void)gettimeofday(&ntime, 0); + looktime = ntime.tv_sec + delay2; + } + if (ntime.tv_sec >= looptime) { + if (trace) + fprintf(fd, "Looking for loops\n"); + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == MASTER) { + to.tsp_type = TSP_LOOP; + to.tsp_vers = TSPVERSION; + to.tsp_seq = sequence++; + to.tsp_hopcnt = MAX_HOPCNT; + (void)strcpy(to.tsp_name, hostname); + bytenetorder(&to); + if (sendto(sock, (char *)&to, sizeof(struct tsp), 0, + (struct sockaddr*)&ntp->dest_addr, + sizeof(ntp->dest_addr)) < 0) { + trace_sendto_err(ntp->dest_addr.sin_addr); + } + } + } + (void)gettimeofday(&ntime, 0); + looptime = ntime.tv_sec + delay2; + } + + wait.tv_sec = min(electiontime,min(looktime,looptime)) - ntime.tv_sec; + if (wait.tv_sec < 0) + wait.tv_sec = 0; + wait.tv_sec += FASTTOUT; + wait.tv_usec = 0; + msg = readmsg(TSP_ANY, ANYADDR, &wait, 0); + + if (msg != NULL) { + /* + * filter stuff not for us + */ + switch (msg->tsp_type) { + case TSP_SETDATE: + case TSP_TRACEOFF: + case TSP_TRACEON: + /* + * XXX check to see they are from ourself + */ + break; + + case TSP_TEST: + case TSP_MSITE: + break; + + case TSP_MASTERUP: + if (!fromnet) { + if (trace) { + fprintf(fd, "slave ignored: "); + print(msg, &from); + } + goto loop; + } + break; + + default: + if (!fromnet + || fromnet->status == IGNORE + || fromnet->status == NOMASTER) { + if (trace) { + fprintf(fd, "slave ignored: "); + print(msg, &from); + } + goto loop; + } + break; + } + + + /* + * now process the message + */ + switch (msg->tsp_type) { + + case TSP_ADJTIME: + if (fromnet != slavenet) + break; + if (!good_host_name(msg->tsp_name)) { + syslog(LOG_NOTICE, + "attempted time adjustment by %s", + msg->tsp_name); + suppress(&from, msg->tsp_name, fromnet); + break; + } + /* + * Speed up loop detection in case we have a loop. + * Otherwise the clocks can race until the loop + * is found. + */ + (void)gettimeofday(&otime, 0); + if (adjtime < otime.tv_sec) + looptime -= (looptime-otime.tv_sec)/2 + 1; + + setmaster(msg); + if (seq != msg->tsp_seq) { + seq = msg->tsp_seq; + synch(tvtomsround(msg->tsp_time)); + } + (void)gettimeofday(&ntime, 0); + electiontime = ntime.tv_sec + delay2; + fastelection = ntime.tv_sec + FASTTOUT; + adjtime = ntime.tv_sec + SAMPLEINTVL*2; + break; + + case TSP_SETTIME: + if (fromnet != slavenet) + break; + if (seq == msg->tsp_seq) + break; + seq = msg->tsp_seq; + + /* adjust time for residence on the queue */ + (void)gettimeofday(&otime, 0); + adj_msg_time(msg,&otime); +#ifdef sgi + (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); + (void)cftime(olddate, "%D %T", &otime.tv_sec); +#else + /* + * the following line is necessary due to syslog + * calling ctime() which clobbers the static buffer + */ + (void)strcpy(olddate, date()); + (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); +#endif /* sgi */ + + if (!good_host_name(msg->tsp_name)) { + syslog(LOG_NOTICE, + "attempted time setting by untrusted %s to %s", + msg->tsp_name, newdate); + suppress(&from, msg->tsp_name, fromnet); + break; + } + + setmaster(msg); + timevalsub(&ntime, &msg->tsp_time, &otime); + if (ntime.tv_sec < MAXADJ && ntime.tv_sec > -MAXADJ) { + /* + * do not change the clock if we can adjust it + */ + synch(tvtomsround(ntime)); + } else { +#ifdef sgi + if (0 > settimeofday(&msg->tsp_time, 0)) { + syslog(LOG_ERR,"settimeofdate(): %m"); + break; + } + logwtmp(&otime, &msg->tsp_time); +#else + logwtmp("|", "date", ""); + (void)settimeofday(&msg->tsp_time, 0); + logwtmp("}", "date", ""); +#endif /* sgi */ + syslog(LOG_NOTICE, + "date changed by %s from %s", + msg->tsp_name, olddate); + if (status & MASTER) + spreadtime(); + } + (void)gettimeofday(&ntime, 0); + electiontime = ntime.tv_sec + delay2; + fastelection = ntime.tv_sec + FASTTOUT; + +/* This patches a bad protocol bug. Imagine a system with several networks, + * where there are a pair of redundant gateways between a pair of networks, + * each running timed. Assume that we start with a third machine mastering + * one of the networks, and one of the gateways mastering the other. + * Imagine that the third machine goes away and the non-master gateway + * decides to replace it. If things are timed just 'right,' we will have + * each gateway mastering one network for a little while. If a SETTIME + * message gets into the network at that time, perhaps from the newly + * masterful gateway as it was taking control, the SETTIME will loop + * forever. Each time a gateway receives it on its slave side, it will + * call spreadtime to forward it on its mastered network. We are now in + * a permanent loop, since the SETTIME msgs will keep any clock + * in the network from advancing. Normally, the 'LOOP' stuff will detect + * and correct the situation. However, with the clocks stopped, the + * 'looptime' timer cannot expire. While they are in this state, the + * masters will try to saturate the network with SETTIME packets. + */ + looptime = ntime.tv_sec + (looptime-otime.tv_sec)/2-1; + break; + + case TSP_MASTERUP: + if (slavenet && fromnet != slavenet) + break; + if (!good_host_name(msg->tsp_name)) { + suppress(&from, msg->tsp_name, fromnet); + if (electiontime > fastelection) + electiontime = fastelection; + break; + } + makeslave(fromnet); + setmaster(msg); + setstatus(); + answerdelay(); + xmit(TSP_SLAVEUP, 0, &from); + (void)gettimeofday(&ntime, 0); + electiontime = ntime.tv_sec + delay2; + fastelection = ntime.tv_sec + FASTTOUT; + refusetime = 0; + break; + + case TSP_MASTERREQ: + if (fromnet->status != SLAVE) + break; + (void)gettimeofday(&ntime, 0); + electiontime = ntime.tv_sec + delay2; + break; + + case TSP_SETDATE: +#ifdef sgi + (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); +#else + (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); +#endif /* sgi */ + schgdate(msg, newdate); + break; + + case TSP_SETDATEREQ: + if (fromnet->status != MASTER) + break; +#ifdef sgi + (void)cftime(newdate, "%D %T", &msg->tsp_time.tv_sec); +#else + (void)strcpy(newdate, ctime(&msg->tsp_time.tv_sec)); +#endif /* sgi */ + htp = findhost(msg->tsp_name); + if (0 == htp) { + syslog(LOG_WARNING, + "DATEREQ from uncontrolled machine"); + break; + } + if (!htp->good) { + syslog(LOG_WARNING, + "attempted date change by untrusted %s to %s", + htp->name, newdate); + spreadtime(); + break; + } + schgdate(msg, newdate); + break; + + case TSP_TRACEON: + traceon(); + break; + + case TSP_TRACEOFF: + traceoff("Tracing ended at %s\n"); + break; + + case TSP_SLAVEUP: + newslave(msg); + break; + + case TSP_ELECTION: + if (fromnet->status == SLAVE) { + (void)gettimeofday(&ntime, 0); + electiontime = ntime.tv_sec + delay2; + fastelection = ntime.tv_sec + FASTTOUT; + seq = 0; + if (!good_host_name(msg->tsp_name)) { + syslog(LOG_NOTICE, + "suppress election of %s", + msg->tsp_name); + to.tsp_type = TSP_QUIT; + electiontime = fastelection; + } else if (cadr.s_addr != from.sin_addr.s_addr + && ntime.tv_sec < refusetime) { +/* if the candidate has to repeat itself, the old code would refuse it + * the second time. That would prevent elections. + */ + to.tsp_type = TSP_REFUSE; + } else { + cadr.s_addr = from.sin_addr.s_addr; + to.tsp_type = TSP_ACCEPT; + refusetime = ntime.tv_sec + 30; + } + taddr = from; + (void)strcpy(tname, msg->tsp_name); + (void)strcpy(to.tsp_name, hostname); + answerdelay(); + if (!acksend(&to, &taddr, tname, + TSP_ACK, 0, 0)) + syslog(LOG_WARNING, + "no answer from candidate %s\n", + tname); + + } else { /* fromnet->status == MASTER */ + htp = addmach(msg->tsp_name, &from,fromnet); + to.tsp_type = TSP_QUIT; + (void)strcpy(to.tsp_name, hostname); + if (!acksend(&to, &htp->addr, htp->name, + TSP_ACK, 0, htp->noanswer)) { + syslog(LOG_ERR, + "no reply from %s to ELECTION-QUIT", + htp->name); + (void)remmach(htp); + } + } + break; + + case TSP_CONFLICT: + if (fromnet->status != MASTER) + break; + /* + * After a network partition, there can be + * more than one master: the first slave to + * come up will notify here the situation. + */ + (void)strcpy(to.tsp_name, hostname); + + /* The other master often gets into the same state, + * with boring results. + */ + ntp = fromnet; /* (acksend() can leave fromnet=0 */ + for (tries = 0; tries < 3; tries++) { + to.tsp_type = TSP_RESOLVE; + answer = acksend(&to, &ntp->dest_addr, + ANYADDR, TSP_MASTERACK, + ntp, 0); + if (answer == NULL) + break; + htp = addmach(answer->tsp_name,&from,ntp); + to.tsp_type = TSP_QUIT; + answer = acksend(&to, &htp->addr, htp->name, + TSP_ACK, 0, htp->noanswer); + if (!answer) { + syslog(LOG_WARNING, + "conflict error: no reply from %s to QUIT", + htp->name); + (void)remmach(htp); + } + } + masterup(ntp); + break; + + case TSP_MSITE: + if (!slavenet) + break; + taddr = from; + to.tsp_type = TSP_MSITEREQ; + to.tsp_vers = TSPVERSION; + to.tsp_seq = 0; + (void)strcpy(to.tsp_name, hostname); + answer = acksend(&to, &slavenet->dest_addr, + ANYADDR, TSP_ACK, + slavenet, 0); + if (answer != NULL + && good_host_name(answer->tsp_name)) { + setmaster(answer); + to.tsp_type = TSP_ACK; + (void)strcpy(to.tsp_name, answer->tsp_name); + bytenetorder(&to); + if (sendto(sock, (char *)&to, + sizeof(struct tsp), 0, + (struct sockaddr*)&taddr, sizeof(taddr)) < 0) { + trace_sendto_err(taddr.sin_addr); + } + } + break; + + case TSP_MSITEREQ: + break; + + case TSP_ACCEPT: + case TSP_REFUSE: + case TSP_RESOLVE: + break; + + case TSP_QUIT: + doquit(msg); /* become a slave */ + break; + + case TSP_TEST: + electiontime = 0; + break; + + case TSP_LOOP: + /* looking for loops of masters */ + if (!(status & MASTER)) + break; + if (fromnet->status == SLAVE) { + if (!strcmp(msg->tsp_name, hostname)) { + /* + * Someone forwarded our message back to + * us. There must be a loop. Tell the + * master of this network to quit. + * + * The other master often gets into + * the same state, with boring results. + */ + ntp = fromnet; + for (tries = 0; tries < 3; tries++) { + to.tsp_type = TSP_RESOLVE; + answer = acksend(&to, &ntp->dest_addr, + ANYADDR, TSP_MASTERACK, + ntp,0); + if (answer == NULL) + break; + taddr = from; + (void)strcpy(tname, answer->tsp_name); + to.tsp_type = TSP_QUIT; + (void)strcpy(to.tsp_name, hostname); + if (!acksend(&to, &taddr, tname, + TSP_ACK, 0, 1)) { + syslog(LOG_ERR, + "no reply from %s to slave LOOP-QUIT", + tname); + } else { + electiontime = 0; + } + } + (void)gettimeofday(&ntime, 0); + looptime = ntime.tv_sec + FASTTOUT; + } else { + if (msg->tsp_hopcnt-- < 1) + break; + bytenetorder(msg); + for (ntp = nettab; ntp != 0; ntp = ntp->next) { + if (ntp->status == MASTER + && 0 > sendto(sock, (char *)msg, + sizeof(struct tsp), 0, + (struct sockaddr*)&ntp->dest_addr, + sizeof(ntp->dest_addr))) + trace_sendto_err(ntp->dest_addr.sin_addr); + } + } + } else { /* fromnet->status == MASTER */ + /* + * We should not have received this from a net + * we are master on. There must be two masters, + * unless the packet was really from us. + */ + if (from.sin_addr.s_addr + == fromnet->my_addr.s_addr) { + if (trace) + fprintf(fd,"discarding forwarded LOOP\n"); + break; + } + + /* + * The other master often gets into the same + * state, with boring results. + */ + ntp = fromnet; + for (tries = 0; tries < 3; tries++) { + to.tsp_type = TSP_RESOLVE; + answer = acksend(&to, &ntp->dest_addr, + ANYADDR, TSP_MASTERACK, + ntp,0); + if (!answer) + break; + htp = addmach(answer->tsp_name, + &from,ntp); + to.tsp_type = TSP_QUIT; + (void)strcpy(to.tsp_name, hostname); + if (!acksend(&to,&htp->addr,htp->name, + TSP_ACK, 0, htp->noanswer)) { + syslog(LOG_ERR, + "no reply from %s to master LOOP-QUIT", + htp->name); + (void)remmach(htp); + } + } + (void)gettimeofday(&ntime, 0); + looptime = ntime.tv_sec + FASTTOUT; + } + break; + default: + if (trace) { + fprintf(fd, "garbage message: "); + print(msg, &from); + } + break; + } + } + goto loop; +} + + +/* + * tell the world who our master is + */ +static void +setmaster(msg) + struct tsp *msg; +{ + if (slavenet + && (slavenet != old_slavenet + || strcmp(msg->tsp_name, master_name) + || old_status != status)) { + (void)strcpy(master_name, msg->tsp_name); + old_slavenet = slavenet; + old_status = status; + + if (status & MASTER) { + syslog(LOG_NOTICE, "submaster to %s", master_name); + if (trace) + fprintf(fd, "submaster to %s\n", master_name); + + } else { + syslog(LOG_NOTICE, "slave to %s", master_name); + if (trace) + fprintf(fd, "slave to %s\n", master_name); + } + } +} + + + +/* + * handle date change request on a slave + */ +static void +schgdate(msg, newdate) + struct tsp *msg; + char *newdate; +{ + struct tsp to; + u_short seq; + struct sockaddr_in taddr; + struct timeval otime; + + if (!slavenet) + return; /* no where to forward */ + + taddr = from; + seq = msg->tsp_seq; + + syslog(LOG_INFO, + "forwarding date change by %s to %s", + msg->tsp_name, newdate); + + /* adjust time for residence on the queue */ + (void)gettimeofday(&otime, 0); + adj_msg_time(msg, &otime); + + to.tsp_type = TSP_SETDATEREQ; + to.tsp_time = msg->tsp_time; + (void)strcpy(to.tsp_name, hostname); + if (!acksend(&to, &slavenet->dest_addr, + ANYADDR, TSP_DATEACK, + slavenet, 0)) + return; /* no answer */ + + xmit(TSP_DATEACK, seq, &taddr); +} + + +/* + * Used before answering a broadcast message to avoid network + * contention and likely collisions. + */ +static void +answerdelay() +{ +#ifdef sgi + sginap(delay1); +#else + struct timeval timeout; + + timeout.tv_sec = 0; + timeout.tv_usec = delay1; + + (void)select(0, (fd_set *)NULL, (fd_set *)NULL, (fd_set *)NULL, + &timeout); + return; +#endif /* sgi */ +} diff --git a/timed.tproj/timed.tproj/timed.8 b/timed.tproj/timed.tproj/timed.8 new file mode 100644 index 0000000..8f8798d --- /dev/null +++ b/timed.tproj/timed.tproj/timed.8 @@ -0,0 +1,219 @@ +.\" Copyright (c) 1980, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)timed.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt TIMED 8 +.Os BSD 4.3 +.Sh NAME +.Nm timed +.Nd time server daemon +.Sh SYNOPSIS +.Nm timed +.Op Fl M +.Op Fl t +.Op Fl d +.Op Fl i Ar network +.Op Fl n Ar network +.Op Fl F Ar host1 host2 ... +.Sh DESCRIPTION +This +is a time server daemon and is normally invoked +at boot time from the +.Xr rc 8 +file. +It synchronizes the host's time with the time of other +machines in a local area network running +.Nm timed 8 . +These time servers will slow down the clocks of some machines +and speed up the clocks of others to bring them to the average network time. +The average network time is computed from measurements of clock differences +using the +.Tn ICMP +timestamp request message. +.Pp +The service provided by +.Nm timed +is based on a master-slave +scheme. +When +.Nm timed 8 +is started on a machine, it asks the master for the network time +and sets the host's clock to that time. +After that, it accepts synchronization messages periodically sent by +the master and calls +.Xr adjtime 2 +to perform the needed corrections on the host's clock. +.Pp +It also communicates with +.Xr date 1 +in order to set the date globally, +and with +.Xr timedc 8 , +a timed control program. +If the machine running the master crashes, then the slaves will elect +a new master from among slaves running with the +.Fl M +flag. +A +.Nm timed +running without the +.Fl M +or +.Fl F +flags will remain a slave. +The +.Fl t +flag enables +.Nm timed +to trace the messages it receives in the +file +.Pa /var/log/timed.log . +Tracing can be turned on or off by the program +.Xr timedc 8 . +The +.Fl d +flag is for debugging the daemon. +It causes the program to not put itself into the background. +Normally +.Nm timed +checks for a master time server on each network to which +it is connected, except as modified by the options described below. +It will request synchronization service from the first master server +located. +If permitted by the +.Fl M +flag, it will provide synchronization service on any attached networks +on which no current master server was detected. +Such a server propagates the time computed by the top-level master. +The +.Fl n +flag, followed by the name of a network which the host is connected to +(see +.Xr networks 5 ) , +overrides the default choice of the +network addresses made by the program. +Each time the +.Fl n +flag appears, that network name is added to a list of valid networks. +All other networks are ignored. +The +.Fl i +flag, followed by the name of a network to which the host is connected +(see +.Xr networks 5 ) , +overrides the default choice of the network addresses made by the program. +Each time the +.Fl i +flag appears, that network name is added to a list of networks to ignore. +All other networks are used by the time daemon. +The +.Fl n +and +.Fl i +flags are meaningless if used together. +.Pp +.Nm Timed +checks for a master time server on each network to which +it is connected, except as modified by the +.Fl n +and +.Fl i +options described above. +If it finds masters on more than one network, it chooses one network +on which to be a "slave," and then periodically checks the other +networks to see if the masters there have disappeared. +.Pp +One way to synchronize a group of machines is to use an NTP daemon to +synchronize the clock of one machine to a distant standard or a radio +receiver and +.Fl F Ar hostname +to tell its timed daemon to trust only itself. +.Pp +Messages printed by the kernel on the system console occur with +interrupts disabled. +This means that the clock stops while they are printing. +A machine with many disk or network hardware problems and consequent +messages cannot keep good time by itself. Each message typically causes +the clock to lose a dozen milliseconds. A time daemon can +correct the result. +.Pp +Messages in the system log about machines that failed to respond +usually indicate machines that crashed or were turned off. +Complaints about machines that failed to respond to initial time +settings are often associated with "multi-homed" machines +that looked for time masters on more than one network and eventually +chose to become a slave on the other network. +.SH WARNING +If two or more time daemons, whether +.Nm timed , +.Xr NTP , +try to adjust the same clock, temporal chaos will result. +If both +.Nm +and another time daemon are run on the same machine, +ensure that the +.Fl F +flag is used, so that +.Nm timed +never attempts to adjust the local clock. +.Pp +The protocol is based on UDP/IP broadcasts. All machines within +the range of a broadcast that are using the TSP protocol must cooperate. +There cannot be more than a single administrative domain using the +.Fl F +flag among all machines reached by a broadcast packet. +Failure to follow this rule is usually indicated by complaints concerning +"untrusted" machines in the system log. +.Sh FILES +.Bl -tag -width /var/log/timed.masterlog -compact +.It Pa /var/log/timed.log +tracing file for timed +.It Pa /var/log/timed.masterlog +log file for master timed +.El +.Sh SEE ALSO +.Xr date 1 , +.Xr adjtime 2 , +.Xr gettimeofday 2 , +.Xr icmp 4 , +.Xr timedc 8 , +.Rs +.%T "TSP: The Time Synchronization Protocol for UNIX 4.3BSD" +.%A R. Gusella +.%A S. Zatti +.Re +.Sh HISTORY +The +.Nm +daemon appeared in +.Bx 4.3 . diff --git a/timed.tproj/timed.tproj/timed.c b/timed.tproj/timed.tproj/timed.c new file mode 100644 index 0000000..01fa981 --- /dev/null +++ b/timed.tproj/timed.tproj/timed.c @@ -0,0 +1,1006 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)timed.c 8.2 (Berkeley) 3/26/95"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif /* sgi */ + +#define TSPTYPES +#include "globals.h" +#include +#include +#include +#include +#include "pathnames.h" +#include +#include +#include +#ifdef sgi +#include +#include +#include +#endif /* sgi */ + +int trace = 0; +int sock, sock_raw = -1; +int status = 0; +u_short sequence; /* sequence number */ +long delay1; +long delay2; + +int nslavenets; /* nets were I could be a slave */ +int nmasternets; /* nets were I could be a master */ +int nignorednets; /* ignored nets */ +int nnets; /* nets I am connected to */ + +FILE *fd; /* trace file FD */ + +jmp_buf jmpenv; + +struct netinfo *nettab = 0; +struct netinfo *slavenet; +int Mflag; +int justquit = 0; +int debug; + +static struct nets { + char *name; + long net; + struct nets *next; +} *nets = 0; + +struct hosttbl hosttbl[NHOSTS+1]; /* known hosts */ + +static struct goodhost { /* hosts that we trust */ + char name[MAXHOSTNAMELEN+1]; + struct goodhost *next; + char perm; +} *goodhosts; + +static char *goodgroup; /* net group of trusted hosts */ +static void checkignorednets __P((void)); +static void pickslavenet __P((struct netinfo *)); +static void add_good_host __P((char *, int)); + +#ifdef sgi +char *timetrim_fn; +char *timetrim_wpat = "long timetrim = %ld;\ndouble tot_adj = %.0f;\ndouble tot_ticks = %.0f;\n/* timed version 2 */\n"; +char *timetrim_rpat = "long timetrim = %ld;\ndouble tot_adj = %lf;\ndouble tot_ticks = %lf;"; +long timetrim; +double tot_adj, hr_adj; /* totals in nsec */ +double tot_ticks, hr_ticks; + +int bufspace = 60*1024; +#endif + + +/* + * The timedaemons synchronize the clocks of hosts in a local area network. + * One daemon runs as master, all the others as slaves. The master + * performs the task of computing clock differences and sends correction + * values to the slaves. + * Slaves start an election to choose a new master when the latter disappears + * because of a machine crash, network partition, or when killed. + * A resolution protocol is used to kill all but one of the masters + * that happen to exist in segments of a partitioned network when the + * network partition is fixed. + * + * Authors: Riccardo Gusella & Stefano Zatti + * + * overhauled at Silicon Graphics + */ +int +main(argc, argv) + int argc; + char *argv[]; +{ + int on; + int ret; + int nflag, iflag; + struct timeval ntime; + struct servent *srvp; + char buf[BUFSIZ], *cp, *cplim; + struct ifconf ifc; + struct ifreq ifreq, ifreqf, *ifr; + register struct netinfo *ntp; + struct netinfo *ntip; + struct netinfo *savefromnet; + struct netent *nentp; + struct nets *nt; + static struct sockaddr_in server; + u_short port; + char c; + extern char *optarg; + extern int optind, opterr; +#ifdef sgi + FILE *timetrim_st; +#endif + +#define IN_MSG "timed: -i and -n make no sense together\n" +#ifdef sgi + struct tms tms; +#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp] [-P trimfile]\n" +#else +#ifdef HAVENIS +#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...] [-G netgp]\n" +#else +#define USAGE "timed: [-dtM] [-i net|-n net] [-F host1 host2 ...]\n" +#endif /* HAVENIS */ +#endif /* sgi */ + +#ifdef lint + ntip = NULL; +#endif + + on = 1; + nflag = OFF; + iflag = OFF; + +#ifdef sgi + if (0 > syssgi(SGI_GETTIMETRIM, &timetrim)) { + perror("timed: syssgi(GETTIMETRIM)"); + timetrim = 0; + } + tot_ticks = hr_ticks = times(&tms); +#endif /* sgi */ + + opterr = 0; + while ((c = getopt(argc, argv, "Mtdn:i:F:G:P:")) != EOF) { + switch (c) { + case 'M': + Mflag = 1; + break; + + case 't': + trace = 1; + break; + + case 'n': + if (iflag) { + fprintf(stderr, IN_MSG); + exit(1); + } else { + nflag = ON; + addnetname(optarg); + } + break; + + case 'i': + if (nflag) { + fprintf(stderr, IN_MSG); + exit(1); + } else { + iflag = ON; + addnetname(optarg); + } + break; + + case 'F': + add_good_host(optarg,1); + while (optind < argc && argv[optind][0] != '-') + add_good_host(argv[optind++], 1); + break; + + case 'd': + debug = 1; + break; + case 'G': + if (goodgroup != 0) { + fprintf(stderr,"timed: only one net group\n"); + exit(1); + } + goodgroup = optarg; + break; +#ifdef sgi + case 'P': + timetrim_fn = optarg; + break; +#endif /* sgi */ + + default: + fprintf(stderr, USAGE); + exit(1); + break; + } + } + if (optind < argc) { + fprintf(stderr, USAGE); + exit(1); + } + +#ifdef sgi + if (timetrim_fn == 0) { + ; + } else if (0 == (timetrim_st = fopen(timetrim_fn, "r+"))) { + if (errno != ENOENT) { + (void)fprintf(stderr,"timed: "); + perror(timetrim_fn); + timetrim_fn = 0; + } + } else { + int i; + long trim; + double adj, ticks; + + i = fscanf(timetrim_st, timetrim_rpat, + &trim, &adj, &ticks); + if (i < 1 + || trim > MAX_TRIM + || trim < -MAX_TRIM + || i == 2 + || (i == 3 + && trim != rint(adj*CLK_TCK/ticks))) { + if (trace && i != EOF) + (void)fprintf(stderr, + "timed: unrecognized contents in %s\n", + timetrim_fn); + } else { + if (0 > syssgi(SGI_SETTIMETRIM, + trim)) { + perror("timed: syssgi(SETTIMETRIM)"); + } else { + timetrim = trim; + } + if (i == 3) + tot_ticks -= ticks; + } + (void)fclose(timetrim_st); + } +#endif /* sgi */ + + /* If we care about which machine is the master, then we must + * be willing to be a master + */ + if (0 != goodgroup || 0 != goodhosts) + Mflag = 1; + + if (gethostname(hostname, sizeof(hostname) - 1) < 0) { + perror("gethostname"); + exit(1); + } + self.l_bak = &self; + self.l_fwd = &self; + self.h_bak = &self; + self.h_fwd = &self; + self.head = 1; + self.good = 1; + + if (goodhosts != 0) /* trust ourself */ + add_good_host(hostname,1); + + srvp = getservbyname("timed", "udp"); + if (srvp == 0) { + fprintf(stderr, "unknown service 'timed/udp'\n"); + exit(1); + } + port = srvp->s_port; + server.sin_addr.s_addr = INADDR_ANY; + server.sin_port = srvp->s_port; + server.sin_family = AF_INET; + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror("socket"); + exit(1); + } + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&on, + sizeof(on)) < 0) { + perror("setsockopt"); + exit(1); + } + if (bind(sock, (struct sockaddr*)&server, sizeof(server))) { + if (errno == EADDRINUSE) + fprintf(stderr,"timed: time daemon already running\n"); + else + perror("bind"); + exit(1); + } +#ifdef sgi + /* + * handle many slaves with our buffer + */ + if (0 > setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&bufspace, + sizeof(bufspace))) { + perror("setsockopt"); + exit(1); + } +#endif /* sgi */ + + /* choose a unique seed for random number generation */ + (void)gettimeofday(&ntime, 0); + srandom(ntime.tv_sec + ntime.tv_usec); + + sequence = random(); /* initial seq number */ + +#ifndef sgi + /* rounds kernel variable time to multiple of 5 ms. */ + ntime.tv_sec = 0; + ntime.tv_usec = -((ntime.tv_usec/1000) % 5) * 1000; + (void)adjtime(&ntime, (struct timeval *)0); +#endif /* sgi */ + + for (nt = nets; nt; nt = nt->next) { + nentp = getnetbyname(nt->name); + if (nentp == 0) { + nt->net = inet_network(nt->name); + if (nt->net != INADDR_NONE) + nentp = getnetbyaddr(nt->net, AF_INET); + } + if (nentp != 0) { + nt->net = nentp->n_net; + } else if (nt->net == INADDR_NONE) { + fprintf(stderr, "timed: unknown net %s\n", nt->name); + exit(1); + } else if (nt->net == INADDR_ANY) { + fprintf(stderr, "timed: bad net %s\n", nt->name); + exit(1); + } else { + fprintf(stderr, + "timed: warning: %s unknown in /etc/networks\n", + nt->name); + } + + if (0 == (nt->net & 0xff000000)) + nt->net <<= 8; + if (0 == (nt->net & 0xff000000)) + nt->net <<= 8; + if (0 == (nt->net & 0xff000000)) + nt->net <<= 8; + } + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { + perror("timed: get interface configuration"); + exit(1); + } + ntp = NULL; +#ifdef sgi +#define size(p) (sizeof(*ifr) - sizeof(ifr->ifr_name)) /* XXX hack. kludge */ +#else +#define size(p) max((p).sa_len, sizeof(p)) +#endif + cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ + for (cp = buf; cp < cplim; + cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) { + ifr = (struct ifreq *)cp; + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + if (!ntp) + ntp = (struct netinfo*)malloc(sizeof(struct netinfo)); + bzero(ntp,sizeof(*ntp)); + ntp->my_addr=((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; + ntp->status = NOMASTER; + ifreq = *ifr; + ifreqf = *ifr; + + if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreqf) < 0) { + perror("get interface flags"); + continue; + } + if ((ifreqf.ifr_flags & IFF_UP) == 0) + continue; + if ((ifreqf.ifr_flags & IFF_BROADCAST) == 0 && + (ifreqf.ifr_flags & IFF_POINTOPOINT) == 0) { + continue; + } + + + if (ioctl(sock, SIOCGIFNETMASK, (char *)&ifreq) < 0) { + perror("get netmask"); + continue; + } + ntp->mask = ((struct sockaddr_in *) + &ifreq.ifr_addr)->sin_addr.s_addr; + + if (ifreqf.ifr_flags & IFF_BROADCAST) { + if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { + perror("get broadaddr"); + continue; + } + ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_broadaddr; + /* What if the broadcast address is all ones? + * So we cannot just mask ntp->dest_addr. */ + ntp->net = ntp->my_addr; + ntp->net.s_addr &= ntp->mask; + } else { + if (ioctl(sock, SIOCGIFDSTADDR, + (char *)&ifreq) < 0) { + perror("get destaddr"); + continue; + } + ntp->dest_addr = *(struct sockaddr_in *)&ifreq.ifr_dstaddr; + ntp->net = ntp->dest_addr.sin_addr; + } + + ntp->dest_addr.sin_port = port; + + for (nt = nets; nt; nt = nt->next) { + if (ntp->net.s_addr == nt->net) + break; + } + if (nflag && !nt || iflag && nt) + continue; + + ntp->next = NULL; + if (nettab == NULL) { + nettab = ntp; + } else { + ntip->next = ntp; + } + ntip = ntp; + ntp = NULL; + } + if (ntp) + (void) free((char *)ntp); + if (nettab == NULL) { + fprintf(stderr, "timed: no network usable\n"); + exit(1); + } + + +#ifdef sgi + (void)schedctl(RENICE,0,10); /* run fast to get good time */ + + /* ticks to delay before responding to a broadcast */ + delay1 = casual(0, CLK_TCK/10); +#else + + /* microseconds to delay before responding to a broadcast */ + delay1 = casual(1, 100*1000); +#endif /* sgi */ + + /* election timer delay in secs. */ + delay2 = casual(MINTOUT, MAXTOUT); + + +#ifdef sgi + (void)_daemonize(debug ? _DF_NOFORK|_DF_NOCHDIR : 0, sock, -1, -1); +#else + if (!debug) + daemon(debug, 0); +#endif /* sgi */ + + if (trace) + traceon(); + openlog("timed", LOG_CONS|LOG_PID, LOG_DAEMON); + + /* + * keep returning here + */ + ret = setjmp(jmpenv); + savefromnet = fromnet; + setstatus(); + + if (Mflag) { + switch (ret) { + + case 0: + checkignorednets(); + pickslavenet(0); + break; + case 1: + /* Just lost our master */ + if (slavenet != 0) + slavenet->status = election(slavenet); + if (!slavenet || slavenet->status == MASTER) { + checkignorednets(); + pickslavenet(0); + } else { + makeslave(slavenet); /* prune extras */ + } + break; + + case 2: + /* Just been told to quit */ + justquit = 1; + pickslavenet(savefromnet); + break; + } + + setstatus(); + if (!(status & MASTER) && sock_raw != -1) { + /* sock_raw is not being used now */ + (void)close(sock_raw); + sock_raw = -1; + } + + if (status == MASTER) + master(); + else + slave(); + + } else { + if (sock_raw != -1) { + (void)close(sock_raw); + sock_raw = -1; + } + + if (ret) { + /* we just lost our master or were told to quit */ + justquit = 1; + } + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == MASTER) + rmnetmachs(ntp); + ntp->status = NOMASTER; + } + checkignorednets(); + pickslavenet(0); + setstatus(); + + slave(); + } + /* NOTREACHED */ +#ifdef lint + return(0); +#endif +} + +/* + * suppress an upstart, untrustworthy, self-appointed master + */ +void +suppress(addr, name,net) + struct sockaddr_in *addr; + char *name; + struct netinfo *net; +{ + struct sockaddr_in tgt; + char tname[MAXHOSTNAMELEN]; + struct tsp msg; + static struct timeval wait; + + if (trace) + fprintf(fd, "suppress: %s\n", name); + tgt = *addr; + (void)strcpy(tname, name); + + while (0 != readmsg(TSP_ANY, ANYADDR, &wait, net)) { + if (trace) + fprintf(fd, "suppress:\tdiscarded packet from %s\n", + name); + } + + syslog(LOG_NOTICE, "suppressing false master %s", tname); + msg.tsp_type = TSP_QUIT; + (void)strcpy(msg.tsp_name, hostname); + (void)acksend(&msg, &tgt, tname, TSP_ACK, 0, 1); +} + +void +lookformaster(ntp) + struct netinfo *ntp; +{ + struct tsp resp, conflict, *answer; + struct timeval ntime; + char mastername[MAXHOSTNAMELEN]; + struct sockaddr_in masteraddr; + + get_goodgroup(0); + ntp->status = SLAVE; + + /* look for master */ + resp.tsp_type = TSP_MASTERREQ; + (void)strcpy(resp.tsp_name, hostname); + answer = acksend(&resp, &ntp->dest_addr, ANYADDR, + TSP_MASTERACK, ntp, 0); + if (answer != 0 && !good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + answer = 0; + } + if (answer == 0) { + /* + * Various conditions can cause conflict: races between + * two just started timedaemons when no master is + * present, or timedaemons started during an election. + * A conservative approach is taken. Give up and became a + * slave, postponing election of a master until first + * timer expires. + */ + ntime.tv_sec = ntime.tv_usec = 0; + answer = readmsg(TSP_MASTERREQ, ANYADDR, &ntime, ntp); + if (answer != 0) { + if (!good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + } + return; + } + + ntime.tv_sec = ntime.tv_usec = 0; + answer = readmsg(TSP_MASTERUP, ANYADDR, &ntime, ntp); + if (answer != 0) { + if (!good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + } + return; + } + + ntime.tv_sec = ntime.tv_usec = 0; + answer = readmsg(TSP_ELECTION, ANYADDR, &ntime, ntp); + if (answer != 0) { + if (!good_host_name(answer->tsp_name)) { + suppress(&from, answer->tsp_name, ntp); + ntp->status = NOMASTER; + } + return; + } + + if (Mflag) + ntp->status = MASTER; + else + ntp->status = NOMASTER; + return; + } + + ntp->status = SLAVE; + (void)strcpy(mastername, answer->tsp_name); + masteraddr = from; + + /* + * If network has been partitioned, there might be other + * masters; tell the one we have just acknowledged that + * it has to gain control over the others. + */ + ntime.tv_sec = 0; + ntime.tv_usec = 300000; + answer = readmsg(TSP_MASTERACK, ANYADDR, &ntime, ntp); + /* + * checking also not to send CONFLICT to ack'ed master + * due to duplicated MASTERACKs + */ + if (answer != NULL && + strcmp(answer->tsp_name, mastername) != 0) { + conflict.tsp_type = TSP_CONFLICT; + (void)strcpy(conflict.tsp_name, hostname); + if (!acksend(&conflict, &masteraddr, mastername, + TSP_ACK, 0, 0)) { + syslog(LOG_ERR, + "error on sending TSP_CONFLICT"); + } + } +} + +/* + * based on the current network configuration, set the status, and count + * networks; + */ +void +setstatus() +{ + struct netinfo *ntp; + + status = 0; + nmasternets = nslavenets = nnets = nignorednets = 0; + if (trace) + fprintf(fd, "Net status:\n"); + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + switch ((int)ntp->status) { + case MASTER: + nmasternets++; + break; + case SLAVE: + nslavenets++; + break; + case NOMASTER: + case IGNORE: + nignorednets++; + break; + } + if (trace) { + fprintf(fd, "\t%-16s", inet_ntoa(ntp->net)); + switch ((int)ntp->status) { + case NOMASTER: + fprintf(fd, "NOMASTER\n"); + break; + case MASTER: + fprintf(fd, "MASTER\n"); + break; + case SLAVE: + fprintf(fd, "SLAVE\n"); + break; + case IGNORE: + fprintf(fd, "IGNORE\n"); + break; + default: + fprintf(fd, "invalid state %d\n", + (int)ntp->status); + break; + } + } + nnets++; + status |= ntp->status; + } + status &= ~IGNORE; + if (trace) + fprintf(fd, + "\tnets=%d masters=%d slaves=%d ignored=%d delay2=%d\n", + nnets, nmasternets, nslavenets, nignorednets, delay2); +} + +void +makeslave(net) + struct netinfo *net; +{ + register struct netinfo *ntp; + + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (ntp->status == SLAVE && ntp != net) + ntp->status = IGNORE; + } + slavenet = net; +} + +/* + * Try to become master over ignored nets.. + */ +static void +checkignorednets() +{ + register struct netinfo *ntp; + + for (ntp = nettab; ntp != NULL; ntp = ntp->next) { + if (!Mflag && ntp->status == SLAVE) + break; + + if (ntp->status == IGNORE || ntp->status == NOMASTER) { + lookformaster(ntp); + if (!Mflag && ntp->status == SLAVE) + break; + } + } +} + +/* + * choose a good network on which to be a slave + * The ignored networks must have already been checked. + * Take a hint about for a good network. + */ +static void +pickslavenet(ntp) + struct netinfo *ntp; +{ + if (slavenet != 0 && slavenet->status == SLAVE) { + makeslave(slavenet); /* prune extras */ + return; + } + + if (ntp == 0 || ntp->status != SLAVE) { + for (ntp = nettab; ntp != 0; ntp = ntp->next) { + if (ntp->status == SLAVE) + break; + } + } + makeslave(ntp); +} + +/* + * returns a random number in the range [inf, sup] + */ +long +casual(inf, sup) + long inf, sup; +{ + double value; + + value = ((double)(random() & 0x7fffffff)) / (0x7fffffff*1.0); + return(inf + (sup - inf)*value); +} + +char * +date() +{ +#ifdef sgi + struct timeval tv; + static char tm[32]; + + (void)gettimeofday(&tv, (struct timezone *)0); + (void)cftime(tm, "%D %T", &tv.tv_sec); + return (tm); +#else + struct timeval tv; + + (void)gettimeofday(&tv, (struct timezone *)0); + return (ctime(&tv.tv_sec)); +#endif /* sgi */ +} + +void +addnetname(name) + char *name; +{ + register struct nets **netlist = &nets; + + while (*netlist) + netlist = &((*netlist)->next); + *netlist = (struct nets *)malloc(sizeof **netlist); + if (*netlist == 0) { + fprintf(stderr,"malloc failed\n"); + exit(1); + } + bzero((char *)*netlist, sizeof(**netlist)); + (*netlist)->name = name; +} + +/* note a host as trustworthy */ +static void +add_good_host(name, perm) + char *name; + int perm; /* 1=not part of the netgroup */ +{ + register struct goodhost *ghp; + register struct hostent *hentp; + + ghp = (struct goodhost*)malloc(sizeof(*ghp)); + if (!ghp) { + syslog(LOG_ERR, "malloc failed"); + exit(1); + } + + bzero((char*)ghp, sizeof(*ghp)); + (void)strncpy(&ghp->name[0], name, sizeof(ghp->name)); + ghp->next = goodhosts; + ghp->perm = perm; + goodhosts = ghp; + + hentp = gethostbyname(name); + if (0 == hentp && perm) + (void)fprintf(stderr, "unknown host %s\n", name); +} + + +/* update our image of the net-group of trustworthy hosts + */ +void +get_goodgroup(force) + int force; +{ +# define NG_DELAY (30*60*CLK_TCK) /* 30 minutes */ + static unsigned long last_update = -NG_DELAY; + unsigned long new_update; + struct hosttbl *htp; + struct goodhost *ghp, **ghpp; + char *mach, *usr, *dom; + struct tms tm; + + + /* if no netgroup, then we are finished */ + if (goodgroup == 0 || !Mflag) + return; + + /* Do not chatter with the netgroup master too often. + */ + new_update = times(&tm); + if (new_update < last_update + NG_DELAY + && !force) + return; + last_update = new_update; + + /* forget the old temporary entries */ + ghpp = &goodhosts; + while (0 != (ghp = *ghpp)) { + if (!ghp->perm) { + *ghpp = ghp->next; + free((char*)ghp); + } else { + ghpp = &ghp->next; + } + } + +#ifdef HAVENIS + /* quit now if we are not one of the trusted masters + */ + if (!innetgr(goodgroup, &hostname[0], 0,0)) { + if (trace) + (void)fprintf(fd, "get_goodgroup: %s not in %s\n", + &hostname[0], goodgroup); + return; + } + if (trace) + (void)fprintf(fd, "get_goodgroup: %s in %s\n", + &hostname[0], goodgroup); + + /* mark the entire netgroup as trusted */ + (void)setnetgrent(goodgroup); + while (getnetgrent(&mach,&usr,&dom)) { + if (0 != mach) + add_good_host(mach,0); + } + (void)endnetgrent(); + + /* update list of slaves */ + for (htp = self.l_fwd; htp != &self; htp = htp->l_fwd) { + htp->good = good_host_name(&htp->name[0]); + } +#endif /* HAVENIS */ +} + + +/* see if a machine is trustworthy + */ +int /* 1=trust hp to change our date */ +good_host_name(name) + char *name; +{ + register struct goodhost *ghp = goodhosts; + register char c; + + if (!ghp || !Mflag) /* trust everyone if no one named */ + return 1; + + c = *name; + do { + if (c == ghp->name[0] + && !strcasecmp(name, ghp->name)) + return 1; /* found him, so say so */ + } while (0 != (ghp = ghp->next)); + + if (!strcasecmp(name,hostname)) /* trust ourself */ + return 1; + + return 0; /* did not find him */ +} diff --git a/timed.tproj/timedc.tproj/Makefile b/timed.tproj/timedc.tproj/Makefile new file mode 100644 index 0000000..ae13f3a --- /dev/null +++ b/timed.tproj/timedc.tproj/Makefile @@ -0,0 +1,51 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = timedc + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = extern.h timedc.h + +CFILES = cmds.c cmdtab.c timedc.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble m.template\ + h.template + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD/$(NAME) + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/timed.tproj/timedc.tproj/Makefile.postamble b/timed.tproj/timedc.tproj/Makefile.postamble new file mode 100644 index 0000000..7b861e1 --- /dev/null +++ b/timed.tproj/timedc.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. +VPATH += :../timed.tproj diff --git a/timed.tproj/timedc.tproj/Makefile.preamble b/timed.tproj/timedc.tproj/Makefile.preamble new file mode 100644 index 0000000..b5b8eac --- /dev/null +++ b/timed.tproj/timedc.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = byteorder.o measure.o cksum.o +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/timed.tproj/timedc.tproj/PB.project b/timed.tproj/timedc.tproj/PB.project new file mode 100644 index 0000000..a4a35bf --- /dev/null +++ b/timed.tproj/timedc.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (extern.h, timedc.h); + OTHER_LINKED = (cmds.c, cmdtab.c, timedc.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, m.template, h.template); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD/$(NAME)"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = timedc; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/timed.tproj/timedc.tproj/cmds.c b/timed.tproj/timedc.tproj/cmds.c new file mode 100644 index 0000000..a844190 --- /dev/null +++ b/timed.tproj/timedc.tproj/cmds.c @@ -0,0 +1,549 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmds.c 8.2 (Berkeley) 3/26/95"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "timedc.h" +#include + +#include +#include +#include + +#include +#include +#include + +#define TSPTYPES +#include + +#ifdef sgi +#include +#include +#else +#define SECHR (60*60) +#define SECDAY (24*SECHR) +#endif /* sgi */ + +# define DATE_PROTO "udp" +# define DATE_PORT "time" + + +int sock; +int sock_raw; +char myname[MAXHOSTNAMELEN]; +struct hostent *hp; +struct sockaddr_in server; +struct sockaddr_in dayaddr; +extern int measure_delta; + +void bytenetorder(struct tsp *); +void bytehostorder(struct tsp *); + + +#define BU ((unsigned long)2208988800) /* seconds before UNIX epoch */ + + +/* compute the difference between our date and another machine + */ +static int /* difference in days from our time */ +daydiff(hostname) + char *hostname; +{ + int i; + int trials; + struct timeval tout, now; + fd_set ready; + struct sockaddr from; + int fromlen; + unsigned long sec; + + + /* wait 2 seconds between 10 tries */ + tout.tv_sec = 2; + tout.tv_usec = 0; + for (trials = 0; trials < 10; trials++) { + /* ask for the time */ + sec = 0; + if (sendto(sock, &sec, sizeof(sec), 0, + (struct sockaddr*)&dayaddr, sizeof(dayaddr)) < 0) { + perror("sendto(sock)"); + return 0; + } + + for (;;) { + FD_ZERO(&ready); + FD_SET(sock, &ready); + i = select(sock+1, &ready, (fd_set *)0, + (fd_set *)0, &tout); + if (i < 0) { + if (errno == EINTR) + continue; + perror("select(date read)"); + return 0; + } + if (0 == i) + break; + + fromlen = sizeof(from); + if (recvfrom(sock,&sec,sizeof(sec),0, + &from,&fromlen) < 0) { + perror("recvfrom(date read)"); + return 0; + } + + sec = ntohl(sec); + if (sec < BU) { + fprintf(stderr, + "%s says it is before 1970: %lu", + hostname, sec); + return 0; + } + sec -= BU; + + (void)gettimeofday(&now, (struct timezone*)0); + return (sec - now.tv_sec); + } + } + + /* if we get here, we tried too many times */ + fprintf(stderr,"%s will not tell us the date\n", hostname); + return 0; +} + + +/* + * Clockdiff computes the difference between the time of the machine on + * which it is called and the time of the machines given as argument. + * The time differences measured by clockdiff are obtained using a sequence + * of ICMP TSTAMP messages which are returned to the sender by the IP module + * in the remote machine. + * In order to compare clocks of machines in different time zones, the time + * is transmitted (as a 32-bit value) in milliseconds since midnight UT. + * If a hosts uses a different time format, it should set the high order + * bit of the 32-bit quantity it transmits. + * However, VMS apparently transmits the time in milliseconds since midnight + * local time (rather than GMT) without setting the high order bit. + * Furthermore, it does not understand daylight-saving time. This makes + * clockdiff behaving inconsistently with hosts running VMS. + * + * In order to reduce the sensitivity to the variance of message transmission + * time, clockdiff sends a sequence of messages. Yet, measures between + * two `distant' hosts can be affected by a small error. The error can, + * however, be reduced by increasing the number of messages sent in each + * measurement. + */ +void +clockdiff(argc, argv) + int argc; + char *argv[]; +{ + int measure_status; + extern int measure(u_long, u_long, char *, struct sockaddr_in*, int); + register int avg_cnt; + register long avg; + struct servent *sp; + + if (argc < 2) { + printf("Usage: clockdiff host ... \n"); + return; + } + + (void)gethostname(myname,sizeof(myname)); + + /* get the address for the date ready */ + sp = getservbyname(DATE_PORT, DATE_PROTO); + if (!sp) { + (void)fprintf(stderr, "%s/%s is an unknown service\n", + DATE_PORT, DATE_PROTO); + dayaddr.sin_port = 0; + } else { + dayaddr.sin_port = sp->s_port; + } + + while (argc > 1) { + argc--; argv++; + hp = gethostbyname(*argv); + if (hp == NULL) { + fprintf(stderr, "timedc: %s: ", *argv); + herror(0); + continue; + } + + server.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, &server.sin_addr.s_addr, hp->h_length); + for (avg_cnt = 0, avg = 0; avg_cnt < 16; avg_cnt++) { + measure_status = measure(10000,100, *argv, &server, 1); + if (measure_status != GOOD) + break; + avg += measure_delta; + } + if (measure_status == GOOD) + measure_delta = avg/avg_cnt; + + switch (measure_status) { + case HOSTDOWN: + printf("%s is down\n", hp->h_name); + continue; + case NONSTDTIME: + printf("%s transmitts a non-standard time format\n", + hp->h_name); + continue; + case UNREACHABLE: + printf("%s is unreachable\n", hp->h_name); + continue; + } + + /* + * Try to get the date only after using ICMP timestamps to + * get the time. This is because the date protocol + * is optional. + */ + if (dayaddr.sin_port != 0) { + dayaddr.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, &dayaddr.sin_addr.s_addr, + hp->h_length); + avg = daydiff(*argv); + if (avg > SECDAY) { + printf("time on %s is %ld days ahead %s\n", + hp->h_name, avg/SECDAY, myname); + continue; + } else if (avg < -SECDAY) { + printf("time on %s is %ld days behind %s\n", + hp->h_name, -avg/SECDAY, myname); + continue; + } + } + + if (measure_delta > 0) { + printf("time on %s is %d ms. ahead of time on %s\n", + hp->h_name, measure_delta, myname); + } else if (measure_delta == 0) { + printf("%s and %s have the same time\n", + hp->h_name, myname); + } else { + printf("time on %s is %d ms. behind time on %s\n", + hp->h_name, -measure_delta, myname); + } + } + return; +} + + +/* + * finds location of master timedaemon + */ +void +msite(argc, argv) + int argc; + char *argv[]; +{ + int cc; + fd_set ready; + struct sockaddr_in dest; + int i, length; + struct sockaddr from; + struct timeval tout; + struct tsp msg; + struct servent *srvp; + char *tgtname; + + if (argc < 1) { + printf("Usage: msite [hostname]\n"); + return; + } + + srvp = getservbyname("timed", "udp"); + if (srvp == 0) { + fprintf(stderr, "udp/timed: unknown service\n"); + return; + } + dest.sin_port = srvp->s_port; + dest.sin_family = AF_INET; + + (void)gethostname(myname, sizeof(myname)); + i = 1; + do { + tgtname = (i >= argc) ? myname : argv[i]; + hp = gethostbyname(tgtname); + if (hp == 0) { + fprintf(stderr, "timedc: %s: ", tgtname); + herror(0); + continue; + } + bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); + + (void)strcpy(msg.tsp_name, myname); + msg.tsp_type = TSP_MSITE; + msg.tsp_vers = TSPVERSION; + bytenetorder(&msg); + if (sendto(sock, &msg, sizeof(struct tsp), 0, + (struct sockaddr*)&dest, + sizeof(struct sockaddr)) < 0) { + perror("sendto"); + continue; + } + + tout.tv_sec = 15; + tout.tv_usec = 0; + FD_ZERO(&ready); + FD_SET(sock, &ready); + if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, + &tout)) { + length = sizeof(struct sockaddr); + cc = recvfrom(sock, &msg, sizeof(struct tsp), 0, + &from, &length); + if (cc < 0) { + perror("recvfrom"); + continue; + } + bytehostorder(&msg); + if (msg.tsp_type == TSP_ACK) { + printf("master timedaemon at %s is %s\n", + tgtname, msg.tsp_name); + } else { + printf("received wrong ack: %s\n", + tsptype[msg.tsp_type]); + } + } else { + printf("communication error with %s\n", tgtname); + } + } while (++i < argc); +} + +/* + * quits timedc + */ +void +quit() +{ + exit(0); +} + + +/* + * Causes the election timer to expire on the selected hosts + * It sends just one udp message per machine, relying on + * reliability of communication channel. + */ +void +testing(argc, argv) + int argc; + char *argv[]; +{ + struct servent *srvp; + struct sockaddr_in sin; + struct tsp msg; + + if (argc < 2) { + printf("Usage: election host1 [host2 ...]\n"); + return; + } + + srvp = getservbyname("timed", "udp"); + if (srvp == 0) { + fprintf(stderr, "udp/timed: unknown service\n"); + return; + } + + while (argc > 1) { + argc--; argv++; + hp = gethostbyname(*argv); + if (hp == NULL) { + fprintf(stderr, "timedc: %s: ", *argv); + herror(0); + argc--; argv++; + continue; + } + sin.sin_port = srvp->s_port; + sin.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, &sin.sin_addr.s_addr, hp->h_length); + + msg.tsp_type = TSP_TEST; + msg.tsp_vers = TSPVERSION; + (void)gethostname(myname, sizeof(myname)); + (void)strncpy(msg.tsp_name, myname, sizeof(msg.tsp_name)); + bytenetorder(&msg); + if (sendto(sock, &msg, sizeof(struct tsp), 0, + (struct sockaddr*)&sin, + sizeof(struct sockaddr)) < 0) { + perror("sendto"); + } + } +} + + +/* + * Enables or disables tracing on local timedaemon + */ +void +tracing(argc, argv) + int argc; + char *argv[]; +{ + int onflag; + int length; + int cc; + fd_set ready; + struct sockaddr_in dest; + struct sockaddr from; + struct timeval tout; + struct tsp msg; + struct servent *srvp; + + if (argc != 2) { + printf("Usage: tracing { on | off }\n"); + return; + } + + srvp = getservbyname("timed", "udp"); + if (srvp == 0) { + fprintf(stderr, "udp/timed: unknown service\n"); + return; + } + dest.sin_port = srvp->s_port; + dest.sin_family = AF_INET; + + (void)gethostname(myname,sizeof(myname)); + hp = gethostbyname(myname); + bcopy(hp->h_addr, &dest.sin_addr.s_addr, hp->h_length); + + if (strcmp(argv[1], "on") == 0) { + msg.tsp_type = TSP_TRACEON; + onflag = ON; + } else { + msg.tsp_type = TSP_TRACEOFF; + onflag = OFF; + } + + (void)strcpy(msg.tsp_name, myname); + msg.tsp_vers = TSPVERSION; + bytenetorder(&msg); + if (sendto(sock, &msg, sizeof(struct tsp), 0, + (struct sockaddr*)&dest, sizeof(struct sockaddr)) < 0) { + perror("sendto"); + return; + } + + tout.tv_sec = 5; + tout.tv_usec = 0; + FD_ZERO(&ready); + FD_SET(sock, &ready); + if (select(FD_SETSIZE, &ready, (fd_set *)0, (fd_set *)0, &tout)) { + length = sizeof(struct sockaddr); + cc = recvfrom(sock, &msg, sizeof(struct tsp), 0, + &from, &length); + if (cc < 0) { + perror("recvfrom"); + return; + } + bytehostorder(&msg); + if (msg.tsp_type == TSP_ACK) + if (onflag) + printf("timed tracing enabled\n"); + else + printf("timed tracing disabled\n"); + else + printf("wrong ack received: %s\n", + tsptype[msg.tsp_type]); + } else + printf("communication error\n"); +} + +int +priv_resources() +{ + int port; + struct sockaddr_in sin; + + sock = socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + perror("opening socket"); + return(-1); + } + + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = 0; + for (port = IPPORT_RESERVED - 1; port > IPPORT_RESERVED / 2; port--) { + sin.sin_port = htons((u_short)port); + if (bind(sock, (struct sockaddr*)&sin, sizeof (sin)) >= 0) + break; + if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) { + perror("bind"); + (void) close(sock); + return(-1); + } + } + if (port == IPPORT_RESERVED / 2) { + fprintf(stderr, "all reserved ports in use\n"); + (void) close(sock); + return(-1); + } + + sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sock_raw < 0) { + perror("opening raw socket"); + (void) close(sock); + return(-1); + } + return(1); +} diff --git a/timed.tproj/timedc.tproj/cmdtab.c b/timed.tproj/timedc.tproj/cmdtab.c new file mode 100644 index 0000000..546a206 --- /dev/null +++ b/timed.tproj/timedc.tproj/cmdtab.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)cmdtab.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include "timedc.h" + +char clockdiffhelp[] = "measures clock differences between machines"; +char helphelp[] = "gets help on commands"; +char msitehelp[] = "finds location of master"; +char quithelp[] = "exits timedc"; +char testinghelp[] = "causes election timers to expire"; +char tracinghelp[] = "turns tracing on or off"; + +struct cmd cmdtab[] = { + { "clockdiff", clockdiffhelp, clockdiff, 0 }, + { "election", testinghelp, testing, 1 }, + { "help", helphelp, help, 0 }, + { "msite", msitehelp, msite, 0 }, + { "quit", quithelp, quit, 0 }, + { "trace", tracinghelp, tracing, 1 }, + { "?", helphelp, help, 0 }, +}; + +int NCMDS = sizeof (cmdtab) / sizeof (cmdtab[0]); diff --git a/timed.tproj/timedc.tproj/extern.h b/timed.tproj/timedc.tproj/extern.h new file mode 100644 index 0000000..22e2e29 --- /dev/null +++ b/timed.tproj/timedc.tproj/extern.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)extern.h 8.1 (Berkeley) 6/6/93 + */ + +#if __STDC__ +struct tsp; +#endif + +extern struct cmd cmdtab[]; + +void bytehostorder __P((struct tsp *)); +void bytenetorder __P((struct tsp *)); +void clockdiff __P((int, char *[])); +void help __P((int, char *[])); +void intr __P((int)); +void makeargv __P((void)); +void msite __P((int, char *[])); +int priv_resources __P((void)); +void quit __P((void)); +void testing __P((int, char *[])); +void tracing __P((int, char *[])); diff --git a/timed.tproj/timedc.tproj/h.template b/timed.tproj/timedc.tproj/h.template new file mode 100644 index 0000000..f3c1b04 --- /dev/null +++ b/timed.tproj/timedc.tproj/h.template @@ -0,0 +1,11 @@ +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import + +@interface $FILENAMESANSEXTENSION$ : NSObject +{ + +} + +@end diff --git a/timed.tproj/timedc.tproj/m.template b/timed.tproj/timedc.tproj/m.template new file mode 100644 index 0000000..1216fe5 --- /dev/null +++ b/timed.tproj/timedc.tproj/m.template @@ -0,0 +1,18 @@ +$$ Lines starting with $$ are not inserted into newly created files +$$ The following substitutions are made: +$$ +$$ $FILENAME$ e.g. foo.m +$$ $FILENAMESANSEXTENSION$ e.g. foo +$$ $DIRECTORY$ e.g. /tmp/MyNewApp +$$ $PROJECTNAME$ e.g. MyNewApp +$$ $SUBPROJECTNAME$ e.g. TheGoodPart.subproj +$$ $USERNAME$ e.g. mwagner +$$ $DATE$ e.g. Jan-1-1994 +$$ +/* $FILENAME$ created by $USERNAME$ on $DATE$ */ + +#import "$FILENAMESANSEXTENSION$.h" + +@implementation $FILENAMESANSEXTENSION$ + +@end diff --git a/timed.tproj/timedc.tproj/timedc.c b/timed.tproj/timedc.tproj/timedc.c new file mode 100644 index 0000000..63e2884 --- /dev/null +++ b/timed.tproj/timedc.tproj/timedc.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)timedc.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#ifdef sgi +#ident "$Revision: 1.1.1.1 $" +#endif + +#include "timedc.h" +#include +#include +#include +#include +#include +#include +#include + +int trace = 0; +FILE *fd = 0; +int margc; +int fromatty; +char *margv[20]; +char cmdline[200]; +jmp_buf toplevel; +static struct cmd *getcmd __P((char *)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + openlog("timedc", LOG_ODELAY, LOG_AUTH); + + /* + * security dictates! + */ + if (priv_resources() < 0) { + fprintf(stderr, "Could not get privileged resources\n"); + exit(1); + } + (void) setuid(getuid()); + + if (--argc > 0) { + c = getcmd(*++argv); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + exit(1); + } + if (c == 0) { + printf("?Invalid command\n"); + exit(1); + } + if (c->c_priv && getuid()) { + printf("?Privileged command\n"); + exit(1); + } + (*c->c_handler)(argc, argv); + exit(0); + } + + fromatty = isatty(fileno(stdin)); + if (setjmp(toplevel)) + putchar('\n'); + (void) signal(SIGINT, intr); + for (;;) { + if (fromatty) { + printf("timedc> "); + (void) fflush(stdout); + } + if (fgets(cmdline, sizeof(cmdline), stdin) == 0) + quit(); + if (cmdline[0] == 0) + break; + makeargv(); + if (margv[0] == 0) + continue; + c = getcmd(margv[0]); + if (c == (struct cmd *)-1) { + printf("?Ambiguous command\n"); + continue; + } + if (c == 0) { + printf("?Invalid command\n"); + continue; + } + if (c->c_priv && getuid()) { + printf("?Privileged command\n"); + continue; + } + (*c->c_handler)(margc, margv); + } + return 0; +} + +void +intr(signo) + int signo; +{ + if (!fromatty) + exit(0); + longjmp(toplevel, 1); +} + + +static struct cmd * +getcmd(name) + char *name; +{ + register char *p, *q; + register struct cmd *c, *found; + register int nmatches, longest; + extern int NCMDS; + + longest = 0; + nmatches = 0; + found = 0; + for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { + p = c->c_name; + for (q = name; *q == *p++; q++) + if (*q == 0) /* exact match? */ + return(c); + if (!*q) { /* the name was a prefix */ + if (q - name > longest) { + longest = q - name; + nmatches = 1; + found = c; + } else if (q - name == longest) + nmatches++; + } + } + if (nmatches > 1) + return((struct cmd *)-1); + return(found); +} + +/* + * Slice a string up into argc/argv. + */ +void +makeargv() +{ + register char *cp; + register char **argp = margv; + + margc = 0; + for (cp = cmdline; *cp;) { + while (isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *argp++ = cp; + margc += 1; + while (*cp != '\0' && !isspace(*cp)) + cp++; + if (*cp == '\0') + break; + *cp++ = '\0'; + } + *argp++ = 0; +} + +#define HELPINDENT (sizeof ("directory")) + +/* + * Help command. + */ +void +help(argc, argv) + int argc; + char *argv[]; +{ + register struct cmd *c; + + if (argc == 1) { + register int i, j, w; + int columns, width = 0, lines; + extern int NCMDS; + + printf("Commands may be abbreviated. Commands are:\n\n"); + for (c = cmdtab; c < &cmdtab[NCMDS]; c++) { + int len = strlen(c->c_name); + + if (len > width) + width = len; + } + width = (width + 8) &~ 7; + columns = 80 / width; + if (columns == 0) + columns = 1; + lines = (NCMDS + columns - 1) / columns; + for (i = 0; i < lines; i++) { + for (j = 0; j < columns; j++) { + c = cmdtab + j * lines + i; + printf("%s", c->c_name); + if (c + lines >= &cmdtab[NCMDS]) { + printf("\n"); + break; + } + w = strlen(c->c_name); + while (w < width) { + w = (w + 8) &~ 7; + putchar('\t'); + } + } + } + return; + } + while (--argc > 0) { + register char *arg; + arg = *++argv; + c = getcmd(arg); + if (c == (struct cmd *)-1) + printf("?Ambiguous help command %s\n", arg); + else if (c == (struct cmd *)0) + printf("?Invalid help command %s\n", arg); + else + printf("%-*s\t%s\n", (int)HELPINDENT, + c->c_name, c->c_help); + } +} diff --git a/timed.tproj/timedc.tproj/timedc.h b/timed.tproj/timedc.tproj/timedc.h new file mode 100644 index 0000000..43ca72c --- /dev/null +++ b/timed.tproj/timedc.tproj/timedc.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)timedc.h 8.1 (Berkeley) 6/6/93 + */ + +#include +#include +#ifdef sgi +#include +#endif +#include +#include +#include + +#include +#include +#include + +extern int errno; + +#define ON 1 +#define OFF 0 + +#define GOOD 1 +#define UNREACHABLE 2 +#define NONSTDTIME 3 +#define HOSTDOWN 0x7fffffff + +struct cmd { + char *c_name; /* command name */ + char *c_help; /* help message */ + void (*c_handler)(); /* routine to do the work */ + int c_priv; /* privileged command */ +}; + +#include "extern.h" diff --git a/traceroute.tproj/Makefile b/traceroute.tproj/Makefile new file mode 100644 index 0000000..75c293b --- /dev/null +++ b/traceroute.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = traceroute + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = traceroute.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble mean.awk\ + median.awk README traceroute.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/traceroute.tproj/Makefile.postamble b/traceroute.tproj/Makefile.postamble new file mode 100644 index 0000000..de54c24 --- /dev/null +++ b/traceroute.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +INSTALL_AS_USER = root # User to chown app to +#INSTALL_AS_GROUP = wheel # Group to chgrp app to +INSTALL_PERMISSIONS = 4555 # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/traceroute.tproj/Makefile.preamble b/traceroute.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/traceroute.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/traceroute.tproj/PB.project b/traceroute.tproj/PB.project new file mode 100644 index 0000000..a843e7e --- /dev/null +++ b/traceroute.tproj/PB.project @@ -0,0 +1,49 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (traceroute.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + mean.awk, + median.awk, + README, + traceroute.8 + ); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = traceroute; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/traceroute.tproj/README b/traceroute.tproj/README new file mode 100644 index 0000000..6d33c6c --- /dev/null +++ b/traceroute.tproj/README @@ -0,0 +1,126 @@ +Tue Dec 27 06:24:24 PST 1988 + +Traceroute is a system administrators utility to trace the route +ip packets from the current system take in getting to some +destination system. See the comments at the front of the +program for a description of its use. + +This program + + a) can only be run by root (it uses raw ip sockets). + + b) REQUIRES A KERNEL MOD to the raw ip output code to run. + +If you want to hack on your kernel, my modified version of the +routine rip_output (in file /sys/netinet/raw_ip.c) is attached. +This code may or may not resemble the code in your kernel. +It may offer you a place to start but I make no promises. +If you do hack your kernel, remember to test everything that uses +raw ip sockets (e.g., ping and egpup/gated) & make sure they still +work. I wish you the best of luck and you're on your own. + +If your system has the ttl bug mentioned in the source, you +might want to fix it while you're in the kernel. (This bug +appears in all releases of BSD up to but not including 4.3tahoe. +If your version of netinet/ip_icmp.c is any earlier than 7.3 +(April, '87), it has the bug.) The fix is just to add the line + ip->ip_ttl = MAXTTL; +after the line + ip->ip_src = t; +(or anywhere before the call to icmp_send) in routine icmp_reflect. + +If you're running this on a pre-4.3bsd system (e.g., Sun 3.x, +Ultrix) that strips ip headers from icmp messages, add -DARCHAIC +to CFLAGS in the Makefile. Also note that rip_output contains +a conditional for a 4.2/4.3 change in the location of a raw +socket's protocol number. I've checked this under 4.3 & Sun OS +3.5 but you should double-check your system to make sure the +appropriate branch of the #if is taken (check the line that +assigned to ip->ip_p in your system's original rip_output). + +A couple of awk programs to massage the traceroute output are +included. "mean.awk" and "median.awk" compute the mean and median +time to each hop, respectively. I've found that something like + + traceroute -q 7 foo.somewhere >t + awk -f median.awk t | graph + +can give you a quick picture of the bad spots on a long +path (median is usually a better noise filter than mean). + +Enjoy. + + - Van Jacobson (van@helios.ee.lbl.gov) + +-------------------- rip_output from /sys/netinet/raw_ip.c +rip_output(m, so) + register struct mbuf *m; + struct socket *so; +{ + register struct ip *ip; + int error; + struct rawcb *rp = sotorawcb(so); + struct sockaddr_in *sin; +#if BSD>=43 + short proto = rp->rcb_proto.sp_protocol; +#else + short proto = so->so_proto->pr_protocol; +#endif + /* + * if the protocol is IPPROTO_RAW, the user handed us a + * complete IP packet. Otherwise, allocate an mbuf for a + * header and fill it in as needed. + */ + if (proto != IPPROTO_RAW) { + /* + * Calculate data length and get an mbuf + * for IP header. + */ + int len = 0; + struct mbuf *m0; + + for (m0 = m; m; m = m->m_next) + len += m->m_len; + + m = m_get(M_DONTWAIT, MT_HEADER); + if (m == 0) { + m = m0; + error = ENOBUFS; + goto bad; + } + m->m_off = MMAXOFF - sizeof(struct ip); + m->m_len = sizeof(struct ip); + m->m_next = m0; + + ip = mtod(m, struct ip *); + ip->ip_tos = 0; + ip->ip_off = 0; + ip->ip_p = proto; + ip->ip_len = sizeof(struct ip) + len; + ip->ip_ttl = MAXTTL; + } else + ip = mtod(m, struct ip *); + + if (rp->rcb_flags & RAW_LADDR) { + sin = (struct sockaddr_in *)&rp->rcb_laddr; + if (sin->sin_family != AF_INET) { + error = EAFNOSUPPORT; + goto bad; + } + ip->ip_src.s_addr = sin->sin_addr.s_addr; + } else + ip->ip_src.s_addr = 0; + + ip->ip_dst = ((struct sockaddr_in *)&rp->rcb_faddr)->sin_addr; + +#if BSD>=43 + return (ip_output(m, rp->rcb_options, &rp->rcb_route, + (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); +#else + return (ip_output(m, (struct mbuf *)0, &rp->rcb_route, + (so->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST)); +#endif +bad: + m_freem(m); + return (error); +} diff --git a/traceroute.tproj/mean.awk b/traceroute.tproj/mean.awk new file mode 100644 index 0000000..e97a56f --- /dev/null +++ b/traceroute.tproj/mean.awk @@ -0,0 +1,50 @@ +#!/bin/awk -f +# +# Copyright (c) 1990, 1993 +# The Regents of the University of California. All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Van Jacobson. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)mean.awk 8.1 (Berkeley) 6/6/93 +# +/^ *[0-9]/ { + # print out the average time to each hop along a route. + tottime = 0; n = 0; + for (f = 5; f <= NF; ++f) { + if ($f == "ms") { + tottime += $(f - 1) + ++n + } + } + if (n > 0) + print $1, tottime/n, median +} diff --git a/traceroute.tproj/median.awk b/traceroute.tproj/median.awk new file mode 100644 index 0000000..1a8d81d --- /dev/null +++ b/traceroute.tproj/median.awk @@ -0,0 +1,67 @@ +#!/bin/awk -f +# +# Copyright (c) 1990, 1993 +# The Regents of the University of California. All rights reserved. +# +# This code is derived from software contributed to Berkeley by +# Van Jacobson. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by the University of +# California, Berkeley and its contributors. +# 4. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# @(#)median.awk 8.1 (Berkeley) 6/6/93 +# +/^ *[0-9]/ { + # print out the median time to each hop along a route. + tottime = 0; n = 0; + for (f = 5; f <= NF; ++f) { + if ($f == "ms") { + ++n + time[n] = $(f - 1) + } + } + if (n > 0) { + # insertion sort the times to find the median + for (i = 2; i <= n; ++i) { + v = time[i]; j = i - 1; + while (time[j] > v) { + time[j+1] = time[j]; + j = j - 1; + if (j < 0) + break; + } + time[j+1] = v; + } + if (n > 1 && (n % 2) == 0) + median = (time[n/2] + time[(n/2) + 1]) / 2 + else + median = time[(n+1)/2] + + print $1, median + } +} diff --git a/traceroute.tproj/traceroute.8 b/traceroute.tproj/traceroute.8 new file mode 100644 index 0000000..5a1ca4c --- /dev/null +++ b/traceroute.tproj/traceroute.8 @@ -0,0 +1,337 @@ +.\" Copyright (c) 1990, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Van Jacobson. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)traceroute.8 8.2 (Berkeley) 6/1/94 +.\" +.Dd June 1, 1994 +.Dt TRACEROUTE 8 +.Os BSD 4.3 +.Sh NAME +.Nm traceroute +.Nd print the route packets take to network host +.Sh SYNOPSIS +.Nm traceroute +.Op Fl m Ar max_ttl +.Op Fl n +.Op Fl p Ar port +.Op Fl q Ar nqueries +.Op Fl r +.Bk -words +.Op Fl s Ar src_addr +.Ek +.Op Fl t Ar tos +.Op Fl w Ar waittime +.Ar host +.Op Ar packetsize +.Sh DESCRIPTION +The Internet is a large and complex aggregation of +network hardware, connected together by gateways. +Tracking the route one's packets follow (or finding the miscreant +gateway that's discarding your packets) can be difficult. +.Nm Traceroute +utilizes the IP protocol `time to live' field and attempts to elicit an +.Tn ICMP +.Dv TIME_EXCEEDED +response from each gateway along the path to some +host. +.Pp +The only mandatory parameter is the destination host name or IP number. +The default probe datagram length is 38 bytes, but this may be increased +by specifying a packet size (in bytes) after the destination host +name. +.Pp +Other options are: +.Bl -tag -width Ds +.It Fl m Ar max_ttl +Set the max time-to-live (max number of hops) used in outgoing probe +packets. The default is 30 hops (the same default used for +.Tn TCP +connections). +.It Fl n +Print hop addresses numerically rather than symbolically and numerically +(saves a nameserver address-to-name lookup for each gateway found on the +path). +.It Fl p Ar port +Set the base +.Tn UDP +.Ar port +number used in probes (default is 33434). +.Nm Traceroute +hopes that nothing is listening on +.Tn UDP +ports +.Em base +to +.Em base+nhops-1 +at the destination host (so an +.Tn ICMP +.Dv PORT_UNREACHABLE +message will +be returned to terminate the route tracing). If something is +listening on a port in the default range, this option can be used +to pick an unused port range. +.It Fl q Ar nqueries +Set the number of probes per ``ttl'' to +.Ar nqueries +(default is three probes). +.It Fl r +Bypass the normal routing tables and send directly to a host on an attached +network. +If the host is not on a directly-attached network, +an error is returned. +This option can be used to ping a local host through an interface +that has no route through it (e.g., after the interface was dropped by +.Xr routed 8 ) . +.It Fl s Ar src_addr +Use the following IP address +(which must be given as an IP number, not +a hostname) as the source address in outgoing probe packets. On +hosts with more than one IP address, this option can be used to +force the source address to be something other than the IP address +of the interface the probe packet is sent on. If the IP address +is not one of this machine's interface addresses, an error is +returned and nothing is sent. +.ne 1i +.It Fl t Ar tos +Set the +.Em type-of-service +in probe packets to the following value (default zero). The value must be +a decimal integer in the range 0 to 255. This option can be used to +see if different types-of-service result in different paths. (If you +are not running a +.Bx 4.3 tahoe +or later system, this may be academic since the normal network +services like telnet and ftp don't let you control the +.Dv TOS ) . +Not all values of +.Dv TOS +are legal or +meaningful \- see the IP spec for definitions. Useful values are +probably +.Ql \-t 16 +(low delay) and +.Ql \-t 8 +(high throughput). +.It Fl v +Verbose output. Received +.Tn ICMP +packets other than +.Dv TIME_EXCEEDED +and +.Dv UNREACHABLE Ns s +are listed. +.It Fl w +Set the time (in seconds) to wait for a response to a probe (default 3 +sec.). +.El +.Pp +This program attempts to trace the route an IP packet would follow to some +internet host by launching +.Tn UDP +probe +packets with a small ttl (time to live) then listening for an +.Tn ICMP +"time exceeded" reply from a gateway. We start our probes +with a ttl of one and increase by one until we get an +.Tn ICMP +"port unreachable" +(which means we got to "host") or hit a max (which +defaults to 30 hops & can be changed with the +.Fl m +flag). Three +probes (changed with +.Fl q +flag) are sent at each ttl setting and a +line is printed showing the ttl, address of the gateway and +round trip time of each probe. If the probe answers come from +different gateways, the address of each responding system will +be printed. If there is no response within a 3 sec. timeout +interval (changed with the +.Fl w +flag), a "*" is printed for that +probe. +.Pp +We don't want the destination +host to process the +.Tn UDP +probe packets so the destination port is set to an +unlikely value (if some clod on the destination is using that +value, it can be changed with the +.Fl p +flag). +.Pp +A sample use and output might be: +.Bd -literal +[yak 71]% traceroute nis.nsf.net. +traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet +1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms +2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms +3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms +4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms +5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms +6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms +7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms +8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms +9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms +10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms +11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms + +.Ed +Note that lines 2 & 3 are the same. This is due to a buggy +kernel on the 2nd hop system \- lbl-csam.arpa \- that forwards +packets with a zero ttl (a bug in the distributed version +of 4.3 +.Tn BSD ) . +Note that you have to guess what path +the packets are taking cross-country since the +.Tn NSFNet +(129.140) +doesn't supply address-to-name translations for its +.Tn NSS Ns es . +.Pp +A more interesting example is: +.Bd -literal +[yak 72]% traceroute allspice.lcs.mit.edu. +traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max +1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms +2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms +3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms +4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms +5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms +6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms +7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms +8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms +9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms +10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms +11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms +12 * * * +13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms +14 * * * +15 * * * +16 * * * +17 * * * +18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms + +.Ed +Note that the gateways 12, 14, 15, 16 & 17 hops away +either don't send +.Tn ICMP +"time exceeded" messages or send them +with a ttl too small to reach us. 14 \- 17 are running the +.Tn MIT +C Gateway code that doesn't send "time exceeded"s. God +only knows what's going on with 12. +.Pp +The silent gateway 12 in the above may be the result of a bug in +the 4.[23] +.Tn BSD +network code (and its derivatives): 4.x (x <= 3) +sends an unreachable message using whatever ttl remains in the +original datagram. Since, for gateways, the remaining ttl is +zero, the +.Tn ICMP +"time exceeded" is guaranteed to not make it back +to us. The behavior of this bug is slightly more interesting +when it appears on the destination system: +.Bd -literal +1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms +2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms +3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms +4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms +5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms +6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms +7 * * * +8 * * * +9 * * * +10 * * * +11 * * * +12 * * * +13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! + +.Ed +Notice that there are 12 "gateways" (13 is the final +destination) and exactly the last half of them are "missing". +What's really happening is that rip (a Sun-3 running Sun OS3.5) +is using the ttl from our arriving datagram as the ttl in its +.Tn ICMP +reply. So, the reply will time out on the return path +(with no notice sent to anyone since +.Tn ICMP's +aren't sent for +.Tn ICMP's ) +until we probe with a ttl that's at least twice the path +length. I.e., rip is really only 7 hops away. A reply that +returns with a ttl of 1 is a clue this problem exists. +.Nm Traceroute +prints a "!" after the time if the ttl is <= 1. +Since vendors ship a lot of obsolete +.Pf ( Tn DEC Ns \'s +Ultrix, Sun 3.x) or +non-standard +.Pq Tn HPUX +software, expect to see this problem +frequently and/or take care picking the target host of your +probes. +Other possible annotations after the time are +.Sy !H , +.Sy !N , +.Sy !P +(got a host, network or protocol unreachable, respectively), +.Sy !S +or +.Sy !F +(source route failed or fragmentation needed \- neither of these should +ever occur and the associated gateway is busted if you see one). If +almost all the probes result in some kind of unreachable, +.Nm traceroute +will give up and exit. +.Pp +This program is intended for use in network testing, measurement +and management. +It should be used primarily for manual fault isolation. +Because of the load it could impose on the network, it is unwise to use +.Nm traceroute +during normal operations or from automated scripts. +.Sh AUTHOR +Implemented by Van Jacobson from a suggestion by Steve Deering. Debugged +by a cast of thousands with particularly cogent suggestions or fixes from +C. Philip Wood, Tim Seaver and Ken Adelman. +.Sh SEE ALSO +.Xr netstat 1 , +.Xr ping 8 +.Sh HISTORY +The +.Nm +command +.Bt diff --git a/traceroute.tproj/traceroute.c b/traceroute.tproj/traceroute.c new file mode 100644 index 0000000..1f8a5fa --- /dev/null +++ b/traceroute.tproj/traceroute.c @@ -0,0 +1,858 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Van Jacobson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)traceroute.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +/* + * traceroute host - trace the route ip packets follow going to "host". + * + * Attempt to trace the route an ip packet would follow to some + * internet host. We find out intermediate hops by launching probe + * packets with a small ttl (time to live) then listening for an + * icmp "time exceeded" reply from a gateway. We start our probes + * with a ttl of one and increase by one until we get an icmp "port + * unreachable" (which means we got to "host") or hit a max (which + * defaults to 30 hops & can be changed with the -m flag). Three + * probes (change with -q flag) are sent at each ttl setting and a + * line is printed showing the ttl, address of the gateway and + * round trip time of each probe. If the probe answers come from + * different gateways, the address of each responding system will + * be printed. If there is no response within a 5 sec. timeout + * interval (changed with the -w flag), a "*" is printed for that + * probe. + * + * Probe packets are UDP format. We don't want the destination + * host to process them so the destination port is set to an + * unlikely value (if some clod on the destination is using that + * value, it can be changed with the -p flag). + * + * A sample use might be: + * + * [yak 71]% traceroute nis.nsf.net. + * traceroute to nis.nsf.net (35.1.1.48), 30 hops max, 56 byte packet + * 1 helios.ee.lbl.gov (128.3.112.1) 19 ms 19 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 39 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 39 ms + * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 39 ms 39 ms 39 ms + * 6 128.32.197.4 (128.32.197.4) 40 ms 59 ms 59 ms + * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 59 ms + * 8 129.140.70.13 (129.140.70.13) 99 ms 99 ms 80 ms + * 9 129.140.71.6 (129.140.71.6) 139 ms 239 ms 319 ms + * 10 129.140.81.7 (129.140.81.7) 220 ms 199 ms 199 ms + * 11 nic.merit.edu (35.1.1.48) 239 ms 239 ms 239 ms + * + * Note that lines 2 & 3 are the same. This is due to a buggy + * kernel on the 2nd hop system -- lbl-csam.arpa -- that forwards + * packets with a zero ttl. + * + * A more interesting example is: + * + * [yak 72]% traceroute allspice.lcs.mit.edu. + * traceroute to allspice.lcs.mit.edu (18.26.0.115), 30 hops max + * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 19 ms 19 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 19 ms 39 ms 39 ms + * 5 ccn-nerif22.Berkeley.EDU (128.32.168.22) 20 ms 39 ms 39 ms + * 6 128.32.197.4 (128.32.197.4) 59 ms 119 ms 39 ms + * 7 131.119.2.5 (131.119.2.5) 59 ms 59 ms 39 ms + * 8 129.140.70.13 (129.140.70.13) 80 ms 79 ms 99 ms + * 9 129.140.71.6 (129.140.71.6) 139 ms 139 ms 159 ms + * 10 129.140.81.7 (129.140.81.7) 199 ms 180 ms 300 ms + * 11 129.140.72.17 (129.140.72.17) 300 ms 239 ms 239 ms + * 12 * * * + * 13 128.121.54.72 (128.121.54.72) 259 ms 499 ms 279 ms + * 14 * * * + * 15 * * * + * 16 * * * + * 17 * * * + * 18 ALLSPICE.LCS.MIT.EDU (18.26.0.115) 339 ms 279 ms 279 ms + * + * (I start to see why I'm having so much trouble with mail to + * MIT.) Note that the gateways 12, 14, 15, 16 & 17 hops away + * either don't send ICMP "time exceeded" messages or send them + * with a ttl too small to reach us. 14 - 17 are running the + * MIT C Gateway code that doesn't send "time exceeded"s. God + * only knows what's going on with 12. + * + * The silent gateway 12 in the above may be the result of a bug in + * the 4.[23]BSD network code (and its derivatives): 4.x (x <= 3) + * sends an unreachable message using whatever ttl remains in the + * original datagram. Since, for gateways, the remaining ttl is + * zero, the icmp "time exceeded" is guaranteed to not make it back + * to us. The behavior of this bug is slightly more interesting + * when it appears on the destination system: + * + * 1 helios.ee.lbl.gov (128.3.112.1) 0 ms 0 ms 0 ms + * 2 lilac-dmc.Berkeley.EDU (128.32.216.1) 39 ms 19 ms 39 ms + * 3 lilac-dmc.Berkeley.EDU (128.32.216.1) 19 ms 39 ms 19 ms + * 4 ccngw-ner-cc.Berkeley.EDU (128.32.136.23) 39 ms 40 ms 19 ms + * 5 ccn-nerif35.Berkeley.EDU (128.32.168.35) 39 ms 39 ms 39 ms + * 6 csgw.Berkeley.EDU (128.32.133.254) 39 ms 59 ms 39 ms + * 7 * * * + * 8 * * * + * 9 * * * + * 10 * * * + * 11 * * * + * 12 * * * + * 13 rip.Berkeley.EDU (128.32.131.22) 59 ms ! 39 ms ! 39 ms ! + * + * Notice that there are 12 "gateways" (13 is the final + * destination) and exactly the last half of them are "missing". + * What's really happening is that rip (a Sun-3 running Sun OS3.5) + * is using the ttl from our arriving datagram as the ttl in its + * icmp reply. So, the reply will time out on the return path + * (with no notice sent to anyone since icmp's aren't sent for + * icmp's) until we probe with a ttl that's at least twice the path + * length. I.e., rip is really only 7 hops away. A reply that + * returns with a ttl of 1 is a clue this problem exists. + * Traceroute prints a "!" after the time if the ttl is <= 1. + * Since vendors ship a lot of obsolete (DEC's Ultrix, Sun 3.x) or + * non-standard (HPUX) software, expect to see this problem + * frequently and/or take care picking the target host of your + * probes. + * + * Other possible annotations after the time are !H, !N, !P (got a host, + * network or protocol unreachable, respectively), !S or !F (source + * route failed or fragmentation needed -- neither of these should + * ever occur and the associated gateway is busted if you see one). If + * almost all the probes result in some kind of unreachable, traceroute + * will give up and exit. + * + * Notes + * ----- + * This program must be run by root or be setuid. (I suggest that + * you *don't* make it setuid -- casual use could result in a lot + * of unnecessary traffic on our poor, congested nets.) + * + * This program requires a kernel mod that does not appear in any + * system available from Berkeley: A raw ip socket using proto + * IPPROTO_RAW must interpret the data sent as an ip datagram (as + * opposed to data to be wrapped in a ip datagram). See the README + * file that came with the source to this program for a description + * of the mods I made to /sys/netinet/raw_ip.c. Your mileage may + * vary. But, again, ANY 4.x (x < 4) BSD KERNEL WILL HAVE TO BE + * MODIFIED TO RUN THIS PROGRAM. + * + * The udp port usage may appear bizarre (well, ok, it is bizarre). + * The problem is that an icmp message only contains 8 bytes of + * data from the original datagram. 8 bytes is the size of a udp + * header so, if we want to associate replies with the original + * datagram, the necessary information must be encoded into the + * udp header (the ip id could be used but there's no way to + * interlock with the kernel's assignment of ip id's and, anyway, + * it would have taken a lot more kernel hacking to allow this + * code to set the ip id). So, to allow two or more users to + * use traceroute simultaneously, we use this task's pid as the + * source port (the high bit is set to move the port number out + * of the "likely" range). To keep track of which probe is being + * replied to (so times and/or hop counts don't get confused by a + * reply that was delayed in transit), we increment the destination + * port number before each probe. + * + * Don't use this as a coding example. I was trying to find a + * routing problem and this code sort-of popped out after 48 hours + * without sleep. I was amazed it ever compiled, much less ran. + * + * I stole the idea for this program from Steve Deering. Since + * the first release, I've learned that had I attended the right + * IETF working group meetings, I also could have stolen it from Guy + * Almes or Matt Mathis. I don't know (or care) who came up with + * the idea first. I envy the originators' perspicacity and I'm + * glad they didn't keep the idea a secret. + * + * Tim Seaver, Ken Adelman and C. Philip Wood provided bug fixes and/or + * enhancements to the original distribution. + * + * I've hacked up a round-trip-route version of this that works by + * sending a loose-source-routed udp datagram through the destination + * back to yourself. Unfortunately, SO many gateways botch source + * routing, the thing is almost worthless. Maybe one day... + * + * -- Van Jacobson (van@helios.ee.lbl.gov) + * Tue Dec 20 03:50:13 PST 1988 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#define MAXPACKET 65535 /* max ip packet size */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#ifndef FD_SET +#define NFDBITS (8*sizeof(fd_set)) +#define FD_SETSIZE NFDBITS +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +#define Fprintf (void)fprintf +#define Sprintf (void)sprintf +#define Printf (void)printf + +/* + * format of a (udp) probe packet. + */ +struct opacket { + struct ip ip; + struct udphdr udp; + u_char seq; /* sequence number of this packet */ + u_char ttl; /* ttl packet left with */ + struct timeval tv; /* time packet left */ +}; + +u_char packet[512]; /* last inbound (icmp) packet */ +struct opacket *outpacket; /* last output (udp) packet */ + +int wait_for_reply __P((int, struct sockaddr_in *)); +void send_probe __P((int, int)); +double deltaT __P((struct timeval *, struct timeval *)); +int packet_ok __P((u_char *, int, struct sockaddr_in *, int)); +void print __P((u_char *, int, struct sockaddr_in *)); +void tvsub __P((struct timeval *, struct timeval *)); +char *inetname __P((struct in_addr)); +void usage __P(()); + +int s; /* receive (icmp) socket file descriptor */ +int sndsock; /* send (udp) socket file descriptor */ +struct timezone tz; /* leftover */ + +struct sockaddr whereto; /* Who to try to reach */ +int datalen; /* How much data */ + +char *source = 0; +char *hostname; + +int nprobes = 3; +int max_ttl = 30; +u_short ident; +u_short port = 32768+666; /* start udp dest port # for probe packets */ +int options; /* socket options */ +int verbose; +int waittime = 5; /* time to wait for response (in seconds) */ +int nflag; /* print addresses numerically */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + struct hostent *hp; + struct protoent *pe; + struct sockaddr_in from, *to; + int ch, i, on, probe, seq, tos, ttl; + + on = 1; + seq = tos = 0; + to = (struct sockaddr_in *)&whereto; + while ((ch = getopt(argc, argv, "dm:np:q:rs:t:w:v")) != EOF) + switch(ch) { + case 'd': + options |= SO_DEBUG; + break; + case 'm': + max_ttl = atoi(optarg); + if (max_ttl <= 1) { + Fprintf(stderr, + "traceroute: max ttl must be >1.\n"); + exit(1); + } + break; + case 'n': + nflag++; + break; + case 'p': + port = atoi(optarg); + if (port < 1) { + Fprintf(stderr, + "traceroute: port must be >0.\n"); + exit(1); + } + break; + case 'q': + nprobes = atoi(optarg); + if (nprobes < 1) { + Fprintf(stderr, + "traceroute: nprobes must be >0.\n"); + exit(1); + } + break; + case 'r': + options |= SO_DONTROUTE; + break; + case 's': + /* + * set the ip source address of the outbound + * probe (e.g., on a multi-homed host). + */ + source = optarg; + break; + case 't': + tos = atoi(optarg); + if (tos < 0 || tos > 255) { + Fprintf(stderr, + "traceroute: tos must be 0 to 255.\n"); + exit(1); + } + break; + case 'v': + verbose++; + break; + case 'w': + waittime = atoi(optarg); + if (waittime <= 1) { + Fprintf(stderr, + "traceroute: wait must be >1 sec.\n"); + exit(1); + } + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + setlinebuf (stdout); + + (void) bzero((char *)&whereto, sizeof(struct sockaddr)); + to->sin_family = AF_INET; + to->sin_addr.s_addr = inet_addr(*argv); + if (to->sin_addr.s_addr != -1) + hostname = *argv; + else { + hp = gethostbyname(*argv); + if (hp) { + to->sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (caddr_t)&to->sin_addr, hp->h_length); + hostname = hp->h_name; + } else { + (void)fprintf(stderr, + "traceroute: unknown host %s\n", *argv); + exit(1); + } + } + if (*++argv) + datalen = atoi(*argv); + if (datalen < 0 || datalen >= MAXPACKET - sizeof(struct opacket)) { + Fprintf(stderr, + "traceroute: packet size must be 0 <= s < %ld.\n", + MAXPACKET - sizeof(struct opacket)); + exit(1); + } + datalen += sizeof(struct opacket); + outpacket = (struct opacket *)malloc((unsigned)datalen); + if (! outpacket) { + perror("traceroute: malloc"); + exit(1); + } + (void) bzero((char *)outpacket, datalen); + outpacket->ip.ip_dst = to->sin_addr; + outpacket->ip.ip_tos = tos; + outpacket->ip.ip_v = IPVERSION; + outpacket->ip.ip_id = 0; + + ident = (getpid() & 0xffff) | 0x8000; + + if ((pe = getprotobyname("icmp")) == NULL) { + Fprintf(stderr, "icmp: unknown protocol\n"); + exit(10); + } + if ((s = socket(AF_INET, SOCK_RAW, pe->p_proto)) < 0) { + perror("traceroute: icmp socket"); + exit(5); + } + if (options & SO_DEBUG) + (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, + (char *)&on, sizeof(on)); + if (options & SO_DONTROUTE) + (void) setsockopt(s, SOL_SOCKET, SO_DONTROUTE, + (char *)&on, sizeof(on)); + + if ((sndsock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { + perror("traceroute: raw socket"); + exit(5); + } +#ifdef SO_SNDBUF + if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, (char *)&datalen, + sizeof(datalen)) < 0) { + perror("traceroute: SO_SNDBUF"); + exit(6); + } +#endif SO_SNDBUF +#ifdef IP_HDRINCL + if (setsockopt(sndsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, + sizeof(on)) < 0) { + perror("traceroute: IP_HDRINCL"); + exit(6); + } +#endif IP_HDRINCL + if (options & SO_DEBUG) + (void) setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, + (char *)&on, sizeof(on)); + if (options & SO_DONTROUTE) + (void) setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, + (char *)&on, sizeof(on)); + + if (source) { + (void) bzero((char *)&from, sizeof(struct sockaddr)); + from.sin_family = AF_INET; + from.sin_addr.s_addr = inet_addr(source); + if (from.sin_addr.s_addr == -1) { + Printf("traceroute: unknown host %s\n", source); + exit(1); + } + outpacket->ip.ip_src = from.sin_addr; +#ifndef IP_HDRINCL + if (bind(sndsock, (struct sockaddr *)&from, sizeof(from)) < 0) { + perror ("traceroute: bind:"); + exit (1); + } +#endif IP_HDRINCL + } + + Fprintf(stderr, "traceroute to %s (%s)", hostname, + inet_ntoa(to->sin_addr)); + if (source) + Fprintf(stderr, " from %s", source); + Fprintf(stderr, ", %d hops max, %d byte packets\n", max_ttl, datalen); + (void) fflush(stderr); + + for (ttl = 1; ttl <= max_ttl; ++ttl) { + u_long lastaddr = 0; + int got_there = 0; + int unreachable = 0; + + Printf("%2d ", ttl); + for (probe = 0; probe < nprobes; ++probe) { + int cc; + struct timeval t1, t2; + struct timezone tz; + struct ip *ip; + + (void) gettimeofday(&t1, &tz); + send_probe(++seq, ttl); + while (cc = wait_for_reply(s, &from)) { + (void) gettimeofday(&t2, &tz); + if ((i = packet_ok(packet, cc, &from, seq))) { + if (from.sin_addr.s_addr != lastaddr) { + print(packet, cc, &from); + lastaddr = from.sin_addr.s_addr; + } + Printf(" %g ms", deltaT(&t1, &t2)); + switch(i - 1) { + case ICMP_UNREACH_PORT: +#ifndef ARCHAIC + ip = (struct ip *)packet; + if (ip->ip_ttl <= 1) + Printf(" !"); +#endif ARCHAIC + ++got_there; + break; + case ICMP_UNREACH_NET: + ++unreachable; + Printf(" !N"); + break; + case ICMP_UNREACH_HOST: + ++unreachable; + Printf(" !H"); + break; + case ICMP_UNREACH_PROTOCOL: + ++got_there; + Printf(" !P"); + break; + case ICMP_UNREACH_NEEDFRAG: + ++unreachable; + Printf(" !F"); + break; + case ICMP_UNREACH_SRCFAIL: + ++unreachable; + Printf(" !S"); + break; + } + break; + } + } + if (cc == 0) + Printf(" *"); + (void) fflush(stdout); + } + putchar('\n'); + if (got_there || unreachable >= nprobes-1) + exit(0); + } +} + +int +wait_for_reply(sock, from) + int sock; + struct sockaddr_in *from; +{ + fd_set fds; + struct timeval wait; + int cc = 0; + int fromlen = sizeof (*from); + + FD_ZERO(&fds); + FD_SET(sock, &fds); + wait.tv_sec = waittime; wait.tv_usec = 0; + + if (select(sock+1, &fds, (fd_set *)0, (fd_set *)0, &wait) > 0) + cc=recvfrom(s, (char *)packet, sizeof(packet), 0, + (struct sockaddr *)from, &fromlen); + + return(cc); +} + + +void +send_probe(seq, ttl) + int seq, ttl; +{ + struct opacket *op = outpacket; + struct ip *ip = &op->ip; + struct udphdr *up = &op->udp; + int i; + + ip->ip_off = 0; + ip->ip_hl = sizeof(*ip) >> 2; + ip->ip_p = IPPROTO_UDP; + ip->ip_len = datalen; + ip->ip_ttl = ttl; + ip->ip_v = IPVERSION; + ip->ip_id = htons(ident+seq); + + up->uh_sport = htons(ident); + up->uh_dport = htons(port+seq); + up->uh_ulen = htons((u_short)(datalen - sizeof(struct ip))); + up->uh_sum = 0; + + op->seq = seq; + op->ttl = ttl; + (void) gettimeofday(&op->tv, &tz); + + i = sendto(sndsock, (char *)outpacket, datalen, 0, &whereto, + sizeof(struct sockaddr)); + if (i < 0 || i != datalen) { + if (i<0) + perror("sendto"); + Printf("traceroute: wrote %s %d chars, ret=%d\n", hostname, + datalen, i); + (void) fflush(stdout); + } +} + + +double +deltaT(t1p, t2p) + struct timeval *t1p, *t2p; +{ + register double dt; + + dt = (double)(t2p->tv_sec - t1p->tv_sec) * 1000.0 + + (double)(t2p->tv_usec - t1p->tv_usec) / 1000.0; + return (dt); +} + + +/* + * Convert an ICMP "type" field to a printable string. + */ +char * +pr_type(t) + u_char t; +{ + static char *ttab[] = { + "Echo Reply", "ICMP 1", "ICMP 2", "Dest Unreachable", + "Source Quench", "Redirect", "ICMP 6", "ICMP 7", + "Echo", "ICMP 9", "ICMP 10", "Time Exceeded", + "Param Problem", "Timestamp", "Timestamp Reply", "Info Request", + "Info Reply" + }; + + if(t > 16) + return("OUT-OF-RANGE"); + + return(ttab[t]); +} + + +int +packet_ok(buf, cc, from, seq) + u_char *buf; + int cc; + struct sockaddr_in *from; + int seq; +{ + register struct icmp *icp; + u_char type, code; + int hlen; +#ifndef ARCHAIC + struct ip *ip; + + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + if (cc < hlen + ICMP_MINLEN) { + if (verbose) + Printf("packet too short (%d bytes) from %s\n", cc, + inet_ntoa(from->sin_addr)); + return (0); + } + cc -= hlen; + icp = (struct icmp *)(buf + hlen); +#else + icp = (struct icmp *)buf; +#endif ARCHAIC + type = icp->icmp_type; code = icp->icmp_code; + if ((type == ICMP_TIMXCEED && code == ICMP_TIMXCEED_INTRANS) || + type == ICMP_UNREACH) { + struct ip *hip; + struct udphdr *up; + + hip = &icp->icmp_ip; + hlen = hip->ip_hl << 2; + up = (struct udphdr *)((u_char *)hip + hlen); + if (hlen + 12 <= cc && hip->ip_p == IPPROTO_UDP && + up->uh_sport == htons(ident) && + up->uh_dport == htons(port+seq)) + return (type == ICMP_TIMXCEED? -1 : code+1); + } +#ifndef ARCHAIC + if (verbose) { + int i; + u_long *lp = (u_long *)&icp->icmp_ip; + + Printf("\n%d bytes from %s to %s", cc, + inet_ntoa(from->sin_addr), inet_ntoa(ip->ip_dst)); + Printf(": icmp type %d (%s) code %d\n", type, pr_type(type), + icp->icmp_code); + for (i = 4; i < cc ; i += sizeof(long)) + Printf("%2d: x%8.8lx\n", i, *lp++); + } +#endif ARCHAIC + return(0); +} + + +void +print(buf, cc, from) + u_char *buf; + int cc; + struct sockaddr_in *from; +{ + struct ip *ip; + int hlen; + + ip = (struct ip *) buf; + hlen = ip->ip_hl << 2; + cc -= hlen; + + if (nflag) + Printf(" %s", inet_ntoa(from->sin_addr)); + else + Printf(" %s (%s)", inetname(from->sin_addr), + inet_ntoa(from->sin_addr)); + + if (verbose) + Printf (" %d bytes to %s", cc, inet_ntoa (ip->ip_dst)); +} + + +#ifdef notyet +/* + * Checksum routine for Internet Protocol family headers (C Version) + */ +u_short +in_cksum(addr, len) + u_short *addr; + int len; +{ + register int nleft = len; + register u_short *w = addr; + register u_short answer; + register int sum = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), + * we add sequential 16 bit words to it, and at the end, fold + * back all the carry bits from the top 16 bits into the lower + * 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) + sum += *(u_char *)w; + + /* + * add back carry outs from top 16 bits to low 16 bits + */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return (answer); +} +#endif notyet + +/* + * Subtract 2 timeval structs: out = out - in. + * Out is assumed to be >= in. + */ +void +tvsub(out, in) + register struct timeval *out, *in; +{ + if ((out->tv_usec -= in->tv_usec) < 0) { + out->tv_sec--; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; +} + + +/* + * Construct an Internet address representation. + * If the nflag has been supplied, give + * numeric value, otherwise try for symbolic name. + */ +char * +inetname(in) + struct in_addr in; +{ + register char *cp; + static char line[50]; + struct hostent *hp; + static char domain[MAXHOSTNAMELEN + 1]; + static int first = 1; + + if (first && !nflag) { + first = 0; + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (cp = index(domain, '.'))) + (void) strcpy(domain, cp + 1); + else + domain[0] = 0; + } + cp = 0; + if (!nflag && in.s_addr != INADDR_ANY) { + hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); + if (hp) { + if ((cp = index(hp->h_name, '.')) && + !strcmp(cp + 1, domain)) + *cp = 0; + cp = hp->h_name; + } + } + if (cp) + (void) strcpy(line, cp); + else { + in.s_addr = ntohl(in.s_addr); +#define C(x) ((x) & 0xff) + Sprintf(line, "%lu.%lu.%lu.%lu", C(in.s_addr >> 24), + C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); + } + return (line); +} + +void +usage() +{ + (void)fprintf(stderr, +"usage: traceroute [-dnrv] [-m max_ttl] [-p port#] [-q nqueries]\n\t\ +[-s src_addr] [-t tos] [-w wait] host [data size]\n"); + exit(1); +} diff --git a/trpt.tproj/Makefile b/trpt.tproj/Makefile new file mode 100644 index 0000000..3a0f3a7 --- /dev/null +++ b/trpt.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = trpt + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = trpt.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble trpt.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/trpt.tproj/Makefile.postamble b/trpt.tproj/Makefile.postamble new file mode 100644 index 0000000..a38e0df --- /dev/null +++ b/trpt.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +INSTALL_AS_GROUP = kmem # Group to chgrp app to +INSTALL_PERMISSIONS = 2555 # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/trpt.tproj/Makefile.preamble b/trpt.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/trpt.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/trpt.tproj/PB.project b/trpt.tproj/PB.project new file mode 100644 index 0000000..e382ae0 --- /dev/null +++ b/trpt.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (trpt.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, trpt.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = trpt; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/trpt.tproj/trpt.8 b/trpt.tproj/trpt.8 new file mode 100644 index 0000000..8cc6c2a --- /dev/null +++ b/trpt.tproj/trpt.8 @@ -0,0 +1,151 @@ +.\" Copyright (c) 1983, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)trpt.8 8.2 (Berkeley) 12/11/93 +.\" +.Dd December 11, 1993 +.Dt TRPT 8 +.Os BSD 4.2 +.Sh NAME +.Nm trpt +.Nd transliterate protocol trace +.Sh SYNOPSIS +.Nm trpt +.Op Fl a +.Op Fl f +.Op Fl j +.Op Fl p Ar hex-address +.Op Fl s +.Op Fl t +.Oo +.Ar system Op Ar core +.Oc +.Sh DESCRIPTION +.Nm Trpt +interrogates the buffer of +.Tn TCP +trace records created +when a socket is marked for +.Dq debugging +(see +.Xr setsockopt 2 ) , +and prints a readable description of these records. +When no options are supplied, +.Nm trpt +prints all the trace records found in the system +grouped according to +.Tn TCP +connection protocol control +block +.Pq Tn PCB . +The following options may be used to +alter this behavior. +.Bl -tag -width Ds +.It Fl a +In addition to the normal output, +print the values of the source and destination +addresses for each packet recorded. +.It Fl f +Follow the trace as it occurs, waiting a short time for additional records +each time the end of the log is reached. +.It Fl j +Just give a list of the protocol control block +addresses for which there are trace records. +.It Fl p +Show only trace records associated with the protocol +control block at the given address +.Ar hex-address . +.It Fl s +In addition to the normal output, +print a detailed description of the packet +sequencing information. +.It Fl t +in addition to the normal output, +print the values for all timers at each +point in the trace. +.El +.Pp +The recommended use of +.Nm trpt +is as follows. +Isolate the problem and enable debugging on the +socket(s) involved in the connection. +Find the address of the protocol control blocks +associated with the sockets using the +.Fl A +option to +.Xr netstat 1 . +Then run +.Nm trpt +with the +.Fl p +option, supplying the associated +protocol control block addresses. +The +.Fl f +option can be used to follow the trace log once the trace is located. +If there are +many sockets using the debugging option, the +.Fl j +option may be useful in checking to see if +any trace records are present for the socket in +question. +.Pp +If debugging is being performed on a system or +core file other than the default, the last two +arguments may be used to supplant the defaults. +.Sh FILES +.Bl -tag -width /dev/kmem -compact +.It Pa /vmunix +.It Pa /dev/kmem +.El +.Sh SEE ALSO +.Xr netstat 1 , +.Xr setsockopt 2 , +.Xr trsp 8 +.Sh DIAGNOSTICS +.Bl -tag -width Ds +.It Sy no namelist +When the system image doesn't +contain the proper symbols to find the trace buffer; +others which should be self explanatory. +.El +.Sh BUGS +Should also print the data for each input or output, +but this is not saved in the race record. +.Pp +The output format is inscrutable and should be described +here. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.2 . diff --git a/trpt.tproj/trpt.c b/trpt.tproj/trpt.c new file mode 100644 index 0000000..63ad900 --- /dev/null +++ b/trpt.tproj/trpt.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1983, 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1983, 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)trpt.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#if BSD >= 199103 +#define NEWVM +#endif +#ifndef NEWVM +#include +#include +#endif +#include +#include +#define PRUREQUESTS +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#define TCPSTATES +#include +#include +#define TCPTIMERS +#include +#include +#include +#define TANAMES +#include + +#include + +#include +#include +#include +#include + +struct tcp_debug tcp_debug[TCP_NDEBUG]; +int tcp_debx; + +struct nlist nl[] = { +#define N_TCP_DEBUG 0 + { "_tcp_debug" }, +#define N_TCP_DEBX 1 + { "_tcp_debx" }, +#ifndef NEWVM +#define N_SYSMAP 2 + { "_Sysmap" }, +#define N_SYSSIZE 3 + { "_Syssize" }, +#endif + { "" }, +}; + +#ifndef NEWVM +static struct pte *Sysmap; +#endif +static caddr_t tcp_pcbs[TCP_NDEBUG]; +static n_time ntime; +static int aflag, kflag, memf, follow, sflag, tflag; + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + int ch, i, jflag, npcbs, numeric(); + char *system, *core, *malloc(); + off_t lseek(); + + jflag = npcbs = 0; + while ((ch = getopt(argc, argv, "afjp:st")) != EOF) + switch (ch) { + case 'a': + ++aflag; + break; + case 'f': + ++follow; + setlinebuf(stdout); + break; + case 'j': + ++jflag; + break; + case 'p': + if (npcbs >= TCP_NDEBUG) { + fputs("trpt: too many pcb's specified\n", + stderr); + exit(1); + } + (void)sscanf(optarg, "%x", (int *)&tcp_pcbs[npcbs++]); + break; + case 's': + ++sflag; + break; + case 't': + ++tflag; + break; + case '?': + default: + (void)fprintf(stderr, +"usage: trpt [-afjst] [-p hex-address] [system [core]]\n"); + exit(1); + } + argc -= optind; + argv += optind; + + core = _PATH_KMEM; + if (argc > 0) { + system = *argv; + argc--, argv++; + if (argc > 0) { + core = *argv; + argc--, argv++; + ++kflag; + } + /* + * Discard setgid privileges if not the running kernel so that + * bad guys can't print interesting stuff from kernel memory. + */ + setgid(getgid()); + } + else + system = _PATH_UNIX; + + if (nlist(system, nl) < 0 || !nl[0].n_value) { + fprintf(stderr, "trpt: %s: no namelist\n", system); + exit(1); + } + if ((memf = open(core, O_RDONLY)) < 0) { + perror(core); + exit(2); + } + if (kflag) { +#ifdef NEWVM + fputs("trpt: can't do core files yet\n", stderr); + exit(1); +#else + off_t off; + + Sysmap = (struct pte *) + malloc((u_int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); + if (!Sysmap) { + fputs("trpt: can't get memory for Sysmap.\n", stderr); + exit(1); + } + off = nl[N_SYSMAP].n_value & ~KERNBASE; + (void)lseek(memf, off, L_SET); + (void)read(memf, (char *)Sysmap, + (int)(nl[N_SYSSIZE].n_value * sizeof(struct pte))); +#endif + } + (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); + if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != + sizeof(tcp_debx)) { + perror("trpt: tcp_debx"); + exit(3); + } + (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); + if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != + sizeof(tcp_debug)) { + perror("trpt: tcp_debug"); + exit(3); + } + /* + * If no control blocks have been specified, figure + * out how many distinct one we have and summarize + * them in tcp_pcbs for sorting the trace records + * below. + */ + if (!npcbs) { + for (i = 0; i < TCP_NDEBUG; i++) { + register struct tcp_debug *td = &tcp_debug[i]; + register int j; + + if (td->td_tcb == 0) + continue; + for (j = 0; j < npcbs; j++) + if (tcp_pcbs[j] == td->td_tcb) + break; + if (j >= npcbs) + tcp_pcbs[npcbs++] = td->td_tcb; + } + if (!npcbs) + exit(0); + } + qsort(tcp_pcbs, npcbs, sizeof(caddr_t), numeric); + if (jflag) { + for (i = 0;;) { + printf("%x", (int)tcp_pcbs[i]); + if (++i == npcbs) + break; + fputs(", ", stdout); + } + putchar('\n'); + } + else for (i = 0; i < npcbs; i++) { + printf("\n%x:\n", (int)tcp_pcbs[i]); + dotrace(tcp_pcbs[i]); + } + exit(0); +} + +dotrace(tcpcb) + register caddr_t tcpcb; +{ + register struct tcp_debug *td; + register int i; + int prev_debx = tcp_debx; + +again: if (--tcp_debx < 0) + tcp_debx = TCP_NDEBUG - 1; + for (i = prev_debx % TCP_NDEBUG; i < TCP_NDEBUG; i++) { + td = &tcp_debug[i]; + if (tcpcb && td->td_tcb != tcpcb) + continue; + ntime = ntohl(td->td_time); + tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, + &td->td_th, td->td_req); + if (i == tcp_debx) + goto done; + } + for (i = 0; i <= tcp_debx % TCP_NDEBUG; i++) { + td = &tcp_debug[i]; + if (tcpcb && td->td_tcb != tcpcb) + continue; + ntime = ntohl(td->td_time); + tcp_trace(td->td_act, td->td_ostate, td->td_tcb, &td->td_cb, + &td->td_th, td->td_req); + } +done: if (follow) { + prev_debx = tcp_debx + 1; + if (prev_debx >= TCP_NDEBUG) + prev_debx = 0; + do { + sleep(1); + (void)klseek(memf, (off_t)nl[N_TCP_DEBX].n_value, L_SET); + if (read(memf, (char *)&tcp_debx, sizeof(tcp_debx)) != + sizeof(tcp_debx)) { + perror("trpt: tcp_debx"); + exit(3); + } + } while (tcp_debx == prev_debx); + (void)klseek(memf, (off_t)nl[N_TCP_DEBUG].n_value, L_SET); + if (read(memf, (char *)tcp_debug, sizeof(tcp_debug)) != + sizeof(tcp_debug)) { + perror("trpt: tcp_debug"); + exit(3); + } + goto again; + } +} + +/* + * Tcp debug routines + */ +/*ARGSUSED*/ +tcp_trace(act, ostate, atp, tp, ti, req) + short act, ostate; + struct tcpcb *atp, *tp; + struct tcpiphdr *ti; + int req; +{ + tcp_seq seq, ack; + int flags, len, win, timer; + + printf("%03ld %s:%s ",(ntime/10) % 1000, tcpstates[ostate], + tanames[act]); + switch (act) { + case TA_INPUT: + case TA_OUTPUT: + case TA_DROP: + if (aflag) { + printf("(src=%s,%u, ", + inet_ntoa(ti->ti_src), ntohs(ti->ti_sport)); + printf("dst=%s,%u)", + inet_ntoa(ti->ti_dst), ntohs(ti->ti_dport)); + } + seq = ti->ti_seq; + ack = ti->ti_ack; + len = ti->ti_len; + win = ti->ti_win; + if (act == TA_OUTPUT) { + seq = ntohl(seq); + ack = ntohl(ack); + len = ntohs(len); + win = ntohs(win); + } + if (act == TA_OUTPUT) + len -= sizeof(struct tcphdr); + if (len) + printf("[%lx..%lx)", seq, seq + len); + else + printf("%lx", seq); + printf("@%lx", ack); + if (win) + printf("(win=%x)", win); + flags = ti->ti_flags; + if (flags) { + register char *cp = "<"; +#define pf(flag, string) { \ + if (ti->ti_flags&flag) { \ + (void)printf("%s%s", cp, string); \ + cp = ","; \ + } \ +} + pf(TH_SYN, "SYN"); + pf(TH_ACK, "ACK"); + pf(TH_FIN, "FIN"); + pf(TH_RST, "RST"); + pf(TH_PUSH, "PUSH"); + pf(TH_URG, "URG"); + printf(">"); + } + break; + case TA_USER: + timer = req >> 8; + req &= 0xff; + printf("%s", prurequests[req]); + if (req == PRU_SLOWTIMO || req == PRU_FASTTIMO) + printf("<%s>", tcptimers[timer]); + break; + } + printf(" -> %s", tcpstates[tp->t_state]); + /* print out internal state of tp !?! */ + printf("\n"); + if (sflag) { + printf("\trcv_nxt %lx rcv_wnd %x snd_una %lx snd_nxt %lx snd_max %lx\n", + tp->rcv_nxt, tp->rcv_wnd, tp->snd_una, tp->snd_nxt, + tp->snd_max); + printf("\tsnd_wl1 %lx snd_wl2 %lx snd_wnd %x\n", tp->snd_wl1, + tp->snd_wl2, tp->snd_wnd); + } + /* print out timers? */ + if (tflag) { + register char *cp = "\t"; + register int i; + + for (i = 0; i < TCPT_NTIMERS; i++) { + if (tp->t_timer[i] == 0) + continue; + printf("%s%s=%d", cp, tcptimers[i], tp->t_timer[i]); + if (i == TCPT_REXMT) + printf(" (t_rxtshft=%d)", tp->t_rxtshift); + cp = ", "; + } + if (*cp != '\t') + putchar('\n'); + } +} + +numeric(c1, c2) + caddr_t *c1, *c2; +{ + return(*c1 - *c2); +} + +klseek(fd, base, off) + int fd, off; + off_t base; +{ + off_t lseek(); + +#ifndef NEWVM + if (kflag) { /* get kernel pte */ + base &= ~KERNBASE; + base = ctob(Sysmap[btop(base)].pg_pfnum) + (base & PGOFSET); + } +#endif + (void)lseek(fd, base, off); +} diff --git a/trsp.tproj/Makefile b/trsp.tproj/Makefile new file mode 100644 index 0000000..4291787 --- /dev/null +++ b/trsp.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = trsp + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = trsp.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble trsp.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/trsp.tproj/Makefile.postamble b/trsp.tproj/Makefile.postamble new file mode 100644 index 0000000..a38e0df --- /dev/null +++ b/trsp.tproj/Makefile.postamble @@ -0,0 +1,110 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of top-level app-wrapper (e.g., Webster.app) +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target + + +# Change defaults assumed by the standard app makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Add Makefile.preamble, Makefile.postamble, and Makefile.dependencies here if +# you would like changes to them to invalidate previous builds. The project +# depends on $(MAKEFILES) so that changes to Makefiles will trigger a re-build. +#MAKEFILES = Makefile + +# Optimization flag passed to compiler: +#OPTIMIZATION_CFLAG = -O + +# Flags always passed to compiler: +#COMMON_CFLAGS = $(PROJECT_SPECIFIC_CFLAGS) -g -Wall + +# Flags passed to compiler in normal 'app' compiles: +#NORMAL_CFLAGS = $(COMMON_CFLAGS) $(OPTIMIZATION_CFLAG) + +# Flags passed to compiler in 'debug' compiles: +#DEBUG_CFLAGS = $(COMMON_CFLAGS) -DDEBUG + +# Flags passed to compiler in 'profile' compiles +#PROFILE_CFLAGS = $(COMMON_CFLAGS) -pg $(OPTIMIZATION_CFLAG) -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User to chown app to +INSTALL_AS_GROUP = kmem # Group to chgrp app to +INSTALL_PERMISSIONS = 2555 # If set, 'install' chmod's executable to this + +# Options to strip for bundles, apps with bundles, and apps without bundles, +# respectively. +#RELOCATABLE_STRIP_OPTS = -x -u +#DYLD_APP_STRIP_OPTS = -A -n +#APP_STRIP_OPTS = +#TOOL_STRIP_OPTS = +#LIBRARY_STRIP_OPTS = -x -S # Note: -S strips debugging symbols +# (Note: APP_STRIP_OPTS and TOOL_STRIP_OPTS default to empty, but +# developers doing their own dynamic loading should set this to +# $(DYLD_APP_STRIP_OPTS)). +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Typical +# user-defined rules are before_install and after_install (please don't +# redefine things like install or app, as they are owned by the top-level +# Makefile API), which are rules that get invoked before and after the install +# target runs. Such rules should be specified with the '::' syntax rather than +# a single colon. diff --git a/trsp.tproj/Makefile.preamble b/trsp.tproj/Makefile.preamble new file mode 100644 index 0000000..2c9003c --- /dev/null +++ b/trsp.tproj/Makefile.preamble @@ -0,0 +1,113 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags here. To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = + +BUNDLELDFLAGS = # use iff project is a bundle +PALETTELDFLAGS = # use iff project is a palette + +## Specify which headers in this project should be published to the outside +## world in a flat header directory given in PUBLIC_HEADER_DIR (which will be +## prepended by DSTROOT, below. Any subset of these public headers can be +## precompiled automatically after installation, with extra user-defined flags. +PUBLIC_HEADER_DIR = +PUBLIC_HEADERS = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +## Configure what is linked in at each level here. Libraries are only used in +## the final 'app' linking step. Final 'app' linking is only done via the +## 'app', 'debug', and 'profile' targets when they are invoked for +## the top-level app. + +# Additional relocatables to be linked in at this level +OTHER_OFILES = +# Additional libs to link apps against ('app' target) +#OTHER_LIBS = +# Additional libs to link apps against ('debug' target) +OTHER_DEBUG_LIBS = +# Additional libs to link apps against ('profile' target) +OTHER_PROF_LIBS = + +# More 'app' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_LIBS = +# More 'debug' libraries when $(JAPANESE) = "YES" +OTHER_JAPANESE_DEBUG_LIBS = +# More 'profile' libs when $(JAPANESE) = "YES" +OTHER_JAPANESE_PROF_LIBS = + +# If this is a bundle, and you *know* the enclosing application will not +# be linking with a library which you require in your bundle code, then +# mention it here so that it gets linked into the bundle. Note that this +# is wasteful but sometimes necessary. +BUNDLE_LIBS = + +## Configure how things get built here. Additional dependencies, sourcefiles, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = +# Precompiled headers to be built before any compilation occurs (e.g., draw.p) +PRECOMPS = + +# Targets to be built before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# Set the following to "YES" if you want the old behavior of recursively +# cleaning all nested subprojects during 'make clean'. +CLEAN_ALL_SUBPROJECTS = + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/trsp.tproj/PB.project b/trsp.tproj/PB.project new file mode 100644 index 0000000..26e29e4 --- /dev/null +++ b/trsp.tproj/PB.project @@ -0,0 +1,41 @@ +{ + DOCICONFILES = (); + FILESTABLE = { + C_FILES = (); + H_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (trsp.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, trsp.8); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = trsp; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/trsp.tproj/trsp.8 b/trsp.tproj/trsp.8 new file mode 100644 index 0000000..19c23b4 --- /dev/null +++ b/trsp.tproj/trsp.8 @@ -0,0 +1,141 @@ +.\" Copyright (c) 1985, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)trsp.8 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt TRSP 8 +.Os BSD 4.2 +.Sh NAME +.Nm trsp +.Nd transliterate sequenced packet protocol trace +.Sh SYNOPSIS +.Nm trsp +.Op Fl a +.Op Fl s +.Op Fl t +.Op Fl j +.Op Fl p Ar hex-address +.Oo +.Ar system Op Ar core +.Oc +.Sh DESCRIPTION +.Xr Trpt +interrogates the buffer of +.Tn SPP +trace records created +when a socket is marked for +.Dq debugging +(see +.Xr setsockopt 2 ) , +and prints a readable description of these records. +When no options are supplied, +.Nm trsp +prints all the trace records found in the system +grouped according to +.Tn SPP +connection protocol control +block +.Pq Tn PCB . +The following options may be used to +alter this behavior. +.Bl -tag -width Ds +.It Fl a +In addition to the normal output, +print the values of the source and destination +addresses for each packet recorded. +.It Fl j +Just give a list of the protocol control block +addresses for which there are trace records. +.It Fl p +Show only trace records associated with the protocol +control block at the given address, +.Ar hex-address . +.It Fl s +in addition to the normal output, +print a detailed description of the packet +sequencing information. +.It Fl t +in addition to the normal output, +print the values for all timers at each +point in the trace, +.El +.Pp +The recommended use of +.Nm trsp +is as follows. +Isolate the problem and enable debugging on the +socket(s) involved in the connection. +Find the address of the protocol control blocks +associated with the sockets using the +.Fl A +option to +.Xr netstat 1 . +Then run +.Nm trsp +with the +.Fl p +option, supplying the associated +protocol control block addresses. If there are +many sockets using the debugging option, the +.Fl j +option may be useful in checking to see if +any trace records are present for the socket in +question. +.Pp +If debugging is being performed on a system or +core file other than the default, the last two +arguments may be used to supplant the defaults. +.Sh FILES +.Bl -tag -width /dev/kmem -compact +.It Pa /vmunix +.It Pa /dev/kmem +.El +.Sh SEE ALSO +.Xr netstat 1 , +.Xr setsockopt 2 +.Sh DIAGNOSTICS +.Bl -tag -width Ds +.It Sy no namelist +When the system image doesn't +contain the proper symbols to find the trace buffer; +others which should be self explanatory. +.Sh BUGS +Should also print the data for each input or output, +but this is not saved in the race record. +.Pp +The output format is inscrutable and should be described +here. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 . diff --git a/trsp.tproj/trsp.c b/trsp.tproj/trsp.c new file mode 100644 index 0000000..6895ff9 --- /dev/null +++ b/trsp.tproj/trsp.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)trsp.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#define PRUREQUESTS +#include + +#include +#include + +#define TCPSTATES +#include +#define TCPTIMERS +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#define SANAMES +#include + +#include +#include +#include +#include + +unsigned long ntime; +int sflag; +int tflag; +int jflag; +int aflag; +int zflag; +int numeric(); +struct nlist nl[] = { + { "_spp_debug" }, + { "_spp_debx" }, + 0 +}; +struct spp_debug spp_debug[SPP_NDEBUG]; +caddr_t spp_pcbs[SPP_NDEBUG]; +int spp_debx; + +main(argc, argv) + int argc; + char **argv; +{ + int i, mask = 0, npcbs = 0; + char *system, *core; + + system = _PATH_UNIX; + core = _PATH_KMEM; + + argc--, argv++; +again: + if (argc > 0 && !strcmp(*argv, "-a")) { + aflag++, argc--, argv++; + goto again; + } + if (argc > 0 && !strcmp(*argv, "-z")) { + zflag++, argc--, argv++; + goto again; + } + if (argc > 0 && !strcmp(*argv, "-s")) { + sflag++, argc--, argv++; + goto again; + } + if (argc > 0 && !strcmp(*argv, "-t")) { + tflag++, argc--, argv++; + goto again; + } + if (argc > 0 && !strcmp(*argv, "-j")) { + jflag++, argc--, argv++; + goto again; + } + if (argc > 0 && !strcmp(*argv, "-p")) { + argc--, argv++; + if (argc < 1) { + fprintf(stderr, "-p: missing sppcb address\n"); + exit(1); + } + if (npcbs >= SPP_NDEBUG) { + fprintf(stderr, "-p: too many pcb's specified\n"); + exit(1); + } + sscanf(*argv, "%x", &spp_pcbs[npcbs++]); + argc--, argv++; + goto again; + } + if (argc > 0) { + system = *argv; + argc--, argv++; + mask++; + /* + * Discard setgid privileges if not the running kernel so that + * bad guys can't print interesting stuff from kernel memory. + */ + setgid(getgid()); + } + if (argc > 0) { + core = *argv; + argc--, argv++; + mask++; + setgid(getgid()); + } + (void) nlist(system, nl); + if (nl[0].n_value == 0) { + fprintf(stderr, "trsp: %s: no namelist\n", system); + exit(1); + } + (void) close(0); + if (open(core, 0) < 0) { + fprintf(stderr, "trsp: "); perror(core); + exit(2); + } + if (mask) { + nl[0].n_value &= 0x7fffffff; + nl[1].n_value &= 0x7fffffff; + } + (void) lseek(0, nl[1].n_value, 0); + if (read(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) { + fprintf(stderr, "trsp: "); perror("spp_debx"); + exit(3); + } + printf("spp_debx=%d\n", spp_debx); + (void) lseek(0, nl[0].n_value, 0); + if (read(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) { + fprintf(stderr, "trsp: "); perror("spp_debug"); + exit(3); + } + /* + * Here, we just want to clear out the old trace data and start over. + */ + if (zflag) { + char *cp = (char *) spp_debug, + *cplim = cp + sizeof(spp_debug); + (void) close(0); + if (open(core, 2) < 0) { + fprintf(stderr, "trsp: "); perror(core); + exit(2); + } + while(cp < cplim) *cp++ = 0; + (void) lseek(0, nl[0].n_value, 0); + if (write(0, spp_debug, sizeof (spp_debug)) != sizeof (spp_debug)) { + fprintf(stderr, "trsp: "); perror("spp_debug"); + exit(3); + } + (void) lseek(0, nl[1].n_value, 0); + spp_debx = 0; + if (write(0, &spp_debx, sizeof (spp_debx)) != sizeof (spp_debx)) { + fprintf(stderr, "trsp: "); perror("spp_debx"); + exit(3); + } + exit(0); + } + /* + * If no control blocks have been specified, figure + * out how many distinct one we have and summarize + * them in spp_pcbs for sorting the trace records + * below. + */ + if (npcbs == 0) { + for (i = 0; i < SPP_NDEBUG; i++) { + register int j; + register struct spp_debug *sd = &spp_debug[i]; + + if (sd->sd_cb == 0) + continue; + for (j = 0; j < npcbs; j++) + if (spp_pcbs[j] == sd->sd_cb) + break; + if (j >= npcbs) + spp_pcbs[npcbs++] = sd->sd_cb; + } + } + qsort(spp_pcbs, npcbs, sizeof (caddr_t), numeric); + if (jflag) { + char *cp = ""; + + for (i = 0; i < npcbs; i++) { + printf("%s%x", cp, spp_pcbs[i]); + cp = ", "; + } + if (*cp) + putchar('\n'); + exit(0); + } + for (i = 0; i < npcbs; i++) { + printf("\n%x:\n", spp_pcbs[i]); + dotrace(spp_pcbs[i]); + } + exit(0); +} + +dotrace(sppcb) + register caddr_t sppcb; +{ + register int i; + register struct spp_debug *sd; + + for (i = spp_debx % SPP_NDEBUG; i < SPP_NDEBUG; i++) { + sd = &spp_debug[i]; + if (sppcb && sd->sd_cb != sppcb) + continue; + ntime = ntohl(sd->sd_time); + spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp, + &sd->sd_si, sd->sd_req); + } + for (i = 0; i < spp_debx % SPP_NDEBUG; i++) { + sd = &spp_debug[i]; + if (sppcb && sd->sd_cb != sppcb) + continue; + ntime = ntohl(sd->sd_time); + spp_trace(sd->sd_act, sd->sd_ostate, sd->sd_cb, &sd->sd_sp, + &sd->sd_si, sd->sd_req); + } +} + +ptime(ms) + int ms; +{ + + printf("%03d ", (ms/10) % 1000); +} + +numeric(c1, c2) + caddr_t *c1, *c2; +{ + + return (*c1 - *c2); +} + +spp_trace(act, ostate, asp, sp, si, req) + short act, ostate; + struct sppcb *asp, *sp; + struct spidp *si; + int req; +{ + u_short seq, ack, len, alo; + int flags, timer; + char *cp; + + if(ostate >= TCP_NSTATES) ostate = 0; + if(act > SA_DROP) act = SA_DROP; + printf("\n"); + ptime(ntime); + printf("%s:%s", tcpstates[ostate], sanames[act]); + + if (si != 0) { + seq = si->si_seq; + ack = si->si_ack; + alo = si->si_alo; + len = si->si_len; + switch (act) { + case SA_RESPOND: + case SA_OUTPUT: + seq = ntohs(seq); + ack = ntohs(ack); + alo = ntohs(alo); + len = ntohs(len); + case SA_INPUT: + case SA_DROP: + if (aflag) { + printf("\n\tsna="); + ns_printhost(&si->si_sna); + printf("\tdna="); + ns_printhost(&si->si_dna); + } + printf("\n\t"); +#define p1(name, f) { \ + printf("%s = %x, ", name, f); \ + } + p1("seq", seq); + p1("ack", ack); + p1("alo", alo); + p1("len", len); + flags = si->si_cc; + printf("flags=%x", flags); +#define pf(name, f) { \ + if (flags & f) { \ + printf("%s%s", cp, name); \ + cp = ","; \ + } \ +} + if (flags) { + char *cp = "<"; + pf("SP_SP", SP_SP); + pf("SP_SA", SP_SA); + pf("SP_OB", SP_OB); + pf("SP_EM", SP_EM); + printf(">"); + } + printf(", "); +#define p2(name, f) { \ + printf("%s = %x, ", name, f); \ +} + p2("sid", si->si_sid); + p2("did", si->si_did); + p2("dt", si->si_dt); + printf("\n\tsna="); + ns_printhost(&si->si_sna); + printf("\tdna="); + ns_printhost(&si->si_dna); + } + } + if(act == SA_USER) { + printf("\treq=%s", prurequests[req&0xff]); + if ((req & 0xff) == PRU_SLOWTIMO) + printf("<%s>", tcptimers[req>>8]); + } + printf(" -> %s", tcpstates[sp->s_state]); + + /* print out internal state of sp !?! */ + printf("\n"); + if (sp == 0) + return; +#define p3(name, f) { \ + printf("%s = %x, ", name, f); \ +} + if (sflag) { + printf("\t"); + p3("rack", sp->s_rack); + p3("ralo", sp->s_ralo); + p3("smax", sp->s_smax); + p3("snxt", sp->s_snxt); + p3("flags", sp->s_flags); +#undef pf +#define pf(name, f) { \ + if (flags & f) { \ + printf("%s%s", cp, name); \ + cp = ","; \ + } \ +} + flags = sp->s_flags; + if (flags || sp->s_oobflags) { + char *cp = "<"; + pf("ACKNOW", SF_ACKNOW); + pf("DELACK", SF_DELACK); + pf("HI", SF_HI); + pf("HO", SF_HO); + pf("PI", SF_PI); + pf("WIN", SF_WIN); + pf("RXT", SF_RXT); + pf("RVD", SF_RVD); + flags = sp->s_oobflags; + pf("SOOB", SF_SOOB); + pf("IOOB", SF_IOOB); + printf(">"); + } + } + /* print out timers? */ + if (tflag) { + char *cp = "\t"; + register int i; + + printf("\n\tTIMERS: "); + p3("idle", sp->s_idle); + p3("force", sp->s_force); + p3("rtseq", sp->s_rtseq); + for (i = 0; i < TCPT_NTIMERS; i++) { + if (sp->s_timer[i] == 0) + continue; + printf("%s%s=%d", cp, tcptimers[i], sp->s_timer[i]); + if (i == TCPT_REXMT) + printf(" (s_rxtshft=%d)", sp->s_rxtshift); + cp = ", "; + } + if (*cp != '\t') + putchar('\n'); + } +} + +ns_printhost(p) +register struct ns_addr *p; +{ + + printf("", + p->x_net.s_net[0], + p->x_net.s_net[1], + p->x_host.s_host[0], + p->x_host.s_host[1], + p->x_host.s_host[2], + p->x_port); + +} + diff --git a/uucpd.tproj/Makefile b/uucpd.tproj/Makefile new file mode 100644 index 0000000..4c25374 --- /dev/null +++ b/uucpd.tproj/Makefile @@ -0,0 +1,50 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = uucpd + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = pathnames.h + +CFILES = uucpd.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +WINDOWS_INSTALLDIR = /usr/libexec +PDO_UNIX_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/uucpd.tproj/Makefile.postamble b/uucpd.tproj/Makefile.postamble new file mode 100644 index 0000000..7ede358 --- /dev/null +++ b/uucpd.tproj/Makefile.postamble @@ -0,0 +1,111 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# ENGLISH - boolean flag set iff $(LANGUAGE) = "English" +# JAPANESE - boolean flag set iff $(LANGUAGE) = "Japanese" +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder that output Makefile +# APPICON - application icon file +# DOCICONS - dock icon files +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A +#COMPATIBILITY_PROJECT_VERSION = 1 + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/uucpd.tproj/Makefile.preamble b/uucpd.tproj/Makefile.preamble new file mode 100644 index 0000000..dcbd1c8 --- /dev/null +++ b/uucpd.tproj/Makefile.preamble @@ -0,0 +1,119 @@ +############################################################################### +# NeXT Makefile.preamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set all three of these if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the specified dir on the +# specified public header files with the specified additional flags. Don't put +# $(DSTROOT) in PUBLIC_HEADER_DIR; this is done for you. +PUBLIC_HEADER_DIR = +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# A virtual root directory (other than /) to be prepended to the $(INSTALLDIR) +# passed from ProjectBuilder. +DSTROOT = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + +-include ../Makefile.include diff --git a/uucpd.tproj/PB.project b/uucpd.tproj/PB.project new file mode 100644 index 0000000..ba6c171 --- /dev/null +++ b/uucpd.tproj/PB.project @@ -0,0 +1,42 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (pathnames.h); + M_FILES = (); + OTHER_LIBS = (); + OTHER_LINKED = (uucpd.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble); + PRECOMPILED_HEADERS = (); + PROJECT_HEADERS = (); + PUBLIC_HEADERS = (); + SUBPROJECTS = (); + }; + GENERATEMAIN = YES; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_DOCUMENTEXTENSIONS = (); + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/libexec; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = uucpd; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/libexec; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/uucpd.tproj/pathnames.h b/uucpd.tproj/pathnames.h new file mode 100644 index 0000000..0383391 --- /dev/null +++ b/uucpd.tproj/pathnames.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 + */ + +#include + +#define _PATH_UUCICO "/usr/lib/uucp/uucico" diff --git a/uucpd.tproj/uucpd.c b/uucpd.tproj/uucpd.c new file mode 100644 index 0000000..4a5445c --- /dev/null +++ b/uucpd.tproj/uucpd.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1985, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Rick Adams. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1985, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)uucpd.c 8.1 (Berkeley) 6/4/93"; +#endif /* not lint */ + +/* + * 4.2BSD TCP/IP server for uucico + * uucico's TCP channel causes this server to be run at the remote end. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" + +struct sockaddr_in hisctladdr; +int hisaddrlen = sizeof hisctladdr; +struct sockaddr_in myctladdr; +int mypid; + +char Username[64]; +char *nenv[] = { + Username, + NULL, +}; +extern char **environ; + +main(argc, argv) +int argc; +char **argv; +{ +#ifndef BSDINETD + register int s, tcp_socket; + struct servent *sp; +#endif !BSDINETD + extern int errno; + int dologout(); + + environ = nenv; +#ifdef BSDINETD + close(1); close(2); + dup(0); dup(0); + hisaddrlen = sizeof (hisctladdr); + if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) { + fprintf(stderr, "%s: ", argv[0]); + perror("getpeername"); + _exit(1); + } + if (fork() == 0) + doit(&hisctladdr); + dologout(); + exit(1); +#else !BSDINETD + sp = getservbyname("uucp", "tcp"); + if (sp == NULL){ + perror("uucpd: getservbyname"); + exit(1); + } + if (fork()) + exit(0); + if ((s=open(_PATH_TTY, 2)) >= 0){ + ioctl(s, TIOCNOTTY, (char *)0); + close(s); + } + + bzero((char *)&myctladdr, sizeof (myctladdr)); + myctladdr.sin_family = AF_INET; + myctladdr.sin_port = sp->s_port; +#ifdef BSD4_2 + tcp_socket = socket(AF_INET, SOCK_STREAM, 0); + if (tcp_socket < 0) { + perror("uucpd: socket"); + exit(1); + } + if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { + perror("uucpd: bind"); + exit(1); + } + listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ + signal(SIGCHLD, dologout); + + for(;;) { + s = accept(tcp_socket, &hisctladdr, &hisaddrlen); + if (s < 0){ + if (errno == EINTR) + continue; + perror("uucpd: accept"); + exit(1); + } + if (fork() == 0) { + close(0); close(1); close(2); + dup(s); dup(s); dup(s); + close(tcp_socket); close(s); + doit(&hisctladdr); + exit(1); + } + close(s); + } +#endif BSD4_2 + +#endif !BSDINETD +} + +doit(sinp) +struct sockaddr_in *sinp; +{ + char user[64], passwd[64]; + char *xpasswd, *crypt(); + struct passwd *pw, *getpwnam(); + + alarm(60); + printf("login: "); fflush(stdout); + if (readline(user, sizeof user) < 0) { + fprintf(stderr, "user read\n"); + return; + } + /* truncate username to 8 characters */ + user[8] = '\0'; + pw = getpwnam(user); + if (pw == NULL) { + fprintf(stderr, "user unknown\n"); + return; + } + if (strcmp(pw->pw_shell, _PATH_UUCICO)) { + fprintf(stderr, "Login incorrect."); + return; + } + if (pw->pw_passwd && *pw->pw_passwd != '\0') { + printf("Password: "); fflush(stdout); + if (readline(passwd, sizeof passwd) < 0) { + fprintf(stderr, "passwd read\n"); + return; + } + xpasswd = crypt(passwd, pw->pw_passwd); + if (strcmp(xpasswd, pw->pw_passwd)) { + fprintf(stderr, "Login incorrect."); + return; + } + } + alarm(0); + sprintf(Username, "USER=%s", user); + dologin(pw, sinp); + setgid(pw->pw_gid); +#ifdef BSD4_2 + initgroups(pw->pw_name, pw->pw_gid); +#endif BSD4_2 + chdir(pw->pw_dir); + setuid(pw->pw_uid); +#ifdef BSD4_2 + execl(UUCICO, "uucico", (char *)0); +#endif BSD4_2 + perror("uucico server: execl"); +} + +readline(p, n) +register char *p; +register int n; +{ + char c; + + while (n-- > 0) { + if (read(0, &c, 1) <= 0) + return(-1); + c &= 0177; + if (c == '\n' || c == '\r') { + *p = '\0'; + return(0); + } + *p++ = c; + } + return(-1); +} + +#include +#ifdef BSD4_2 +#include +#endif BSD4_2 + +#define SCPYN(a, b) strncpy(a, b, sizeof (a)) + +struct utmp utmp; + +dologout() +{ + union wait status; + int pid, wtmp; + +#ifdef BSDINETD + while ((pid=wait((int *)&status)) > 0) { +#else !BSDINETD + while ((pid=wait3((int *)&status,WNOHANG,0)) > 0) { +#endif !BSDINETD + wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND); + if (wtmp >= 0) { + sprintf(utmp.ut_line, "uucp%.4d", pid); + SCPYN(utmp.ut_name, ""); + SCPYN(utmp.ut_host, ""); + (void) time(&utmp.ut_time); + (void) write(wtmp, (char *)&utmp, sizeof (utmp)); + (void) close(wtmp); + } + } +} + +/* + * Record login in wtmp file. + */ +dologin(pw, sin) +struct passwd *pw; +struct sockaddr_in *sin; +{ + char line[32]; + char remotehost[32]; + int wtmp, f; + struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, + sizeof (struct in_addr), AF_INET); + + if (hp) { + strncpy(remotehost, hp->h_name, sizeof (remotehost)); + endhostent(); + } else + strncpy(remotehost, inet_ntoa(sin->sin_addr), + sizeof (remotehost)); + wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND); + if (wtmp >= 0) { + /* hack, but must be unique and no tty line */ + sprintf(line, "uucp%.4d", getpid()); + SCPYN(utmp.ut_line, line); + SCPYN(utmp.ut_name, pw->pw_name); + SCPYN(utmp.ut_host, remotehost); + time(&utmp.ut_time); + (void) write(wtmp, (char *)&utmp, sizeof (utmp)); + (void) close(wtmp); + } + if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) { + struct lastlog ll; + + time(&ll.ll_time); + lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); + strcpy(line, remotehost); + SCPYN(ll.ll_line, line); + SCPYN(ll.ll_host, remotehost); + (void) write(f, (char *) &ll, sizeof ll); + (void) close(f); + } +} diff --git a/wall.tproj/Makefile b/wall.tproj/Makefile new file mode 100644 index 0000000..9d20c3c --- /dev/null +++ b/wall.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = wall + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ttymsg.c wall.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble Makefile.dist\ + wall.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/wall.tproj/Makefile.dist b/wall.tproj/Makefile.dist new file mode 100644 index 0000000..65abb61 --- /dev/null +++ b/wall.tproj/Makefile.dist @@ -0,0 +1,8 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= wall +SRCS= ttymsg.c wall.c +BINGRP= tty +BINMODE=2555 + +.include diff --git a/wall.tproj/Makefile.postamble b/wall.tproj/Makefile.postamble new file mode 100644 index 0000000..851f5b0 --- /dev/null +++ b/wall.tproj/Makefile.postamble @@ -0,0 +1,123 @@ +############################################################################### +# NeXT Makefile.postamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES + # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A + # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 + # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 + # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wmost +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root + # User/group ownership +INSTALL_AS_GROUP = tty + # (probably want to set both of these) +INSTALL_PERMISSIONS = 2555 + # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S + # for .a archives +#DYNAMIC_STRIP_OPTS = -S + # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# +# Note: on MS Windows, executables, have an extension, so rules and dependencies +# for generated tools should use $(EXECUTABLE_EXT) on the end. diff --git a/wall.tproj/Makefile.preamble b/wall.tproj/Makefile.preamble new file mode 100644 index 0000000..74ce95a --- /dev/null +++ b/wall.tproj/Makefile.preamble @@ -0,0 +1,130 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. + diff --git a/wall.tproj/PB.project b/wall.tproj/PB.project new file mode 100644 index 0000000..d0b5d25 --- /dev/null +++ b/wall.tproj/PB.project @@ -0,0 +1,27 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (); + OTHER_LINKED = (ttymsg.c, wall.c); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, Makefile.dist, wall.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = wall; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/wall.tproj/ttymsg.c b/wall.tproj/ttymsg.c new file mode 100644 index 0000000..45e4d2d --- /dev/null +++ b/wall.tproj/ttymsg.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Display the contents of a uio structure on a terminal. Used by wall(1), + * syslogd(8), and talkd(8). Forks and finishes in child if write would block, + * waiting up to tmout seconds. Returns pointer to error string on unexpected + * error; string is not newline-terminated. Various "normal" errors are + * ignored (exclusive-use, lack of permission, etc.). + */ +char * +ttymsg(iov, iovcnt, line, tmout) + struct iovec *iov; + int iovcnt; + char *line; + int tmout; +{ + static char device[MAXNAMLEN] = _PATH_DEV; + static char errbuf[1024]; + register int cnt, fd, left, wret; + struct iovec localiov[6]; + int forked = 0; + + if (iovcnt > sizeof(localiov) / sizeof(localiov[0])) + return ("too many iov's (change code in wall/ttymsg.c)"); + + (void) strcpy(device + sizeof(_PATH_DEV) - 1, line); + if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) { + /* A slash is an attempt to break security... */ + (void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"", + device); + return (errbuf); + } + + /* + * open will fail on slip lines or exclusive-use lines + * if not running as root; not an error. + */ + if ((fd = open(device, O_WRONLY|O_NONBLOCK, 0)) < 0) { + if (errno == EBUSY || errno == EACCES) + return (NULL); + (void) snprintf(errbuf, sizeof(errbuf), + "%s: %s", device, strerror(errno)); + return (errbuf); + } + + for (cnt = left = 0; cnt < iovcnt; ++cnt) + left += iov[cnt].iov_len; + + for (;;) { + wret = writev(fd, iov, iovcnt); + if (wret >= left) + break; + if (wret >= 0) { + left -= wret; + if (iov != localiov) { + bcopy(iov, localiov, + iovcnt * sizeof(struct iovec)); + iov = localiov; + } + for (cnt = 0; wret >= iov->iov_len; ++cnt) { + wret -= iov->iov_len; + ++iov; + --iovcnt; + } + if (wret) { + iov->iov_base += wret; + iov->iov_len -= wret; + } + continue; + } + if (errno == EWOULDBLOCK) { + int cpid, off = 0; + + if (forked) { + (void) close(fd); + _exit(1); + } + cpid = fork(); + if (cpid < 0) { + (void) snprintf(errbuf, sizeof(errbuf), + "fork: %s", strerror(errno)); + (void) close(fd); + return (errbuf); + } + if (cpid) { /* parent */ + (void) close(fd); + return (NULL); + } + forked++; + /* wait at most tmout seconds */ + (void) signal(SIGALRM, SIG_DFL); + (void) signal(SIGTERM, SIG_DFL); /* XXX */ + (void) sigsetmask(0); + (void) alarm((u_int)tmout); + (void) fcntl(fd, O_NONBLOCK, &off); + continue; + } + /* + * We get ENODEV on a slip line if we're running as root, + * and EIO if the line just went away. + */ + if (errno == ENODEV || errno == EIO) + break; + (void) close(fd); + if (forked) + _exit(1); + (void) snprintf(errbuf, sizeof(errbuf), + "%s: %s", device, strerror(errno)); + return (errbuf); + } + + (void) close(fd); + if (forked) + _exit(0); + return (NULL); +} diff --git a/wall.tproj/wall.1 b/wall.tproj/wall.1 new file mode 100644 index 0000000..ed2f4c9 --- /dev/null +++ b/wall.tproj/wall.1 @@ -0,0 +1,63 @@ +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)wall.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt WALL 1 +.Os BSD 4 +.Sh NAME +.Nm wall +.Nd write a message to users +.Sh SYNOPSIS +.Nm wall +.Op Ar file +.Sh DESCRIPTION +.Nm Wall +displays the contents of +.Ar file +or, by default, its standard input, on the terminals of all +currently logged in users. +.Pp +Only the super-user can write on the +terminals of users who have chosen +to deny messages or are using a program which +automatically denies messages. +.Sh SEE ALSO +.Xr mesg 1 , +.Xr talk 1 , +.Xr write 1 , +.Xr shutdown 8 +.Sh HISTORY +A +.Nm +command appeared in +.At v7 . diff --git a/wall.tproj/wall.c b/wall.tproj/wall.c new file mode 100644 index 0000000..e08a8dd --- /dev/null +++ b/wall.tproj/wall.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1988, 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +/* + * This program is not related to David Wall, whose Stanford Ph.D. thesis + * is entitled "Mechanisms for Broadcast and Selective Broadcast". + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +void makemsg __P((char *)); + +#define IGNOREUSER "sleeper" + +int nobanner; +int mbufsize; +char *mbuf; + +/* ARGSUSED */ +int +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + int ch; + struct iovec iov; + struct utmp utmp; + FILE *fp; + char *p, *ttymsg(); + char line[sizeof(utmp.ut_line) + 1]; + + while ((ch = getopt(argc, argv, "n")) != EOF) + switch (ch) { + case 'n': + /* undoc option for shutdown: suppress banner */ + if (geteuid() == 0) + nobanner = 1; + break; + case '?': + default: +usage: + (void)fprintf(stderr, "usage: wall [file]\n"); + exit(1); + } + argc -= optind; + argv += optind; + if (argc > 1) + goto usage; + + makemsg(*argv); + + if (!(fp = fopen(_PATH_UTMP, "r"))) { + (void)fprintf(stderr, "wall: cannot read %s.\n", _PATH_UTMP); + exit(1); + } + iov.iov_base = mbuf; + iov.iov_len = mbufsize; + /* NOSTRICT */ + while (fread((char *)&utmp, sizeof(utmp), 1, fp) == 1) { + if (!utmp.ut_name[0] || + !strncmp(utmp.ut_name, IGNOREUSER, sizeof(utmp.ut_name))) + continue; + strncpy(line, utmp.ut_line, sizeof(utmp.ut_line)); + line[sizeof(utmp.ut_line)] = '\0'; + if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL) + (void)fprintf(stderr, "wall: %s\n", p); + } + exit(0); +} + +void +makemsg(fname) + char *fname; +{ + register int ch, cnt; + struct tm *lt; + struct passwd *pw; + struct stat sbuf; + time_t now, time(); + FILE *fp; + int fd; + char *p, *whom, hostname[MAXHOSTNAMELEN], lbuf[100], tmpname[15]; + char *getlogin(), *strcpy(), *ttyname(); + + (void)strcpy(tmpname, _PATH_TMP); + (void)strcat(tmpname, "/wall.XXXXXX"); + if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) { + (void)fprintf(stderr, "wall: can't open temporary file.\n"); + exit(1); + } + (void)unlink(tmpname); + + if (!nobanner) { + if (!(whom = getlogin())) + whom = (pw = getpwuid(getuid())) ? pw->pw_name : "???"; + (void)gethostname(hostname, sizeof(hostname)); + (void)time(&now); + lt = localtime(&now); + + /* + * all this stuff is to blank out a square for the message; + * we wrap message lines at column 79, not 80, because some + * terminals wrap after 79, some do not, and we can't tell. + * Which means that we may leave a non-blank character + * in column 80, but that can't be helped. + */ + (void)fprintf(fp, "\r%79s\r\n", " "); + (void)sprintf(lbuf, "Broadcast Message from %s@%s", + whom, hostname); + (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf); + (void)sprintf(lbuf, " (%s) at %d:%02d ...", ttyname(2), + lt->tm_hour, lt->tm_min); + (void)fprintf(fp, "%-79.79s\r\n", lbuf); + } + (void)fprintf(fp, "%79s\r\n", " "); + + if (fname && !(freopen(fname, "r", stdin))) { + (void)fprintf(stderr, "wall: can't read %s.\n", fname); + exit(1); + } + while (fgets(lbuf, sizeof(lbuf), stdin)) + for (cnt = 0, p = lbuf; (ch = *p) != '\0'; ++p, ++cnt) { + if (cnt == 79 || ch == '\n') { + for (; cnt < 79; ++cnt) + putc(' ', fp); + putc('\r', fp); + putc('\n', fp); + cnt = 0; + } else + putc(ch, fp); + } + (void)fprintf(fp, "%79s\r\n", " "); + rewind(fp); + + if (fstat(fd, &sbuf)) { + (void)fprintf(stderr, "wall: can't stat temporary file.\n"); + exit(1); + } + mbufsize = sbuf.st_size; + if (!(mbuf = malloc((u_int)mbufsize))) { + (void)fprintf(stderr, "wall: out of memory.\n"); + exit(1); + } + if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) { + (void)fprintf(stderr, "wall: can't read temporary file.\n"); + exit(1); + } + (void)close(fd); +} diff --git a/ypbind.tproj/Makefile b/ypbind.tproj/Makefile new file mode 100644 index 0000000..548fccf --- /dev/null +++ b/ypbind.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypbind + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ypbind.c + +OTHERSRCS = Makefile Makefile.dist Makefile.postamble Makefile.preamble\ + yp.x + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypbind.tproj/Makefile.dist b/ypbind.tproj/Makefile.dist new file mode 100644 index 0000000..901e614 --- /dev/null +++ b/ypbind.tproj/Makefile.dist @@ -0,0 +1,8 @@ +# from: @(#)Makefile 5.8 (Berkeley) 7/28/90 +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:00 wsanchez Exp $ + +PROG= ypbind +NOMAN= +CFLAGS+=-DDAEMON -DHEURISTIC + +.include diff --git a/ypbind.tproj/Makefile.postamble b/ypbind.tproj/Makefile.postamble new file mode 100644 index 0000000..cc6d6ab --- /dev/null +++ b/ypbind.tproj/Makefile.postamble @@ -0,0 +1,108 @@ +############################################################################### +# NeXT Makefile.postamble Template +# Copyright 1993, NeXT Computer, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project, sub-project, bundle, or +# palette. Each node in the project's tree of sub-projects and bundles +# should have it's own Makefile.preamble and Makefile.postamble. Additional +# rules (e.g., after_install) that are defined by the developer should be +# defined in this file. +# +############################################################################### +# +# Here are the variables exported by the common "app" makefiles that can be +# used in any customizations you make to the template below: +# +# PRODUCT_ROOT - Name of the directory to which resources are copied. +# OFILE_DIR - Directory into which .o object files are generated. +# (Note that this name is calculated based on the target +# architectures specified in Project Builder). +# DERIVED_SRC_DIR - Directory used for all other derived files +# ALL_CFLAGS - All the flags passed to the cc(1) driver for compilations +# +# NAME - name of application, bundle, subproject, palette, etc. +# LANGUAGE - langage in which the project is written (default "English") +# LOCAL_RESOURCES - localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES - non-localized resources of project +# PROJECTVERSION - version of ProjectBuilder project (NS3.X = 1.1, NS4.0 = 2.0) +# ICONSECTIONS - Specifies icon sections when linking executable +# +# CLASSES - Class implementation files in project. +# HFILES - Header files in project. +# MFILES - Other Objective-C source files in project. +# CFILES - Other C source files in project. +# PSWFILES - .psw files in the project +# PSWMFILES - .pswm files in the project +# SUBPROJECTS - Subprojects of this project +# BUNDLES - Bundle subprojects of this project +# OTHERSRCS - Other miscellaneous sources of this project +# OTHERLINKED - Source files not matching a standard source extention +# +# LIBS - Libraries to link with when making app target +# DEBUG_LIBS - Libraries to link with when making debug target +# PROF_LIBS - Libraries to link with when making profile target +# OTHERLINKEDOFILES - Other relocatable files to (always) link in. +# +# APP_MAKEFILE_DIR - Directory in which to find generic set of Makefiles +# MAKEFILEDIR - Directory in which to find $(MAKEFILE) +# MAKEFILE - Top level mechanism Makefile (e.g., app.make, bundle.make) +# INSTALLDIR - Directory app will be installed into by 'install' target +# +############################################################################### + + +# Change defaults assumed by the standard makefiles here. Edit the +# following default values as appropriate. (Note that if no Makefile.postamble +# exists, these values will have defaults set in common.make). + +# Versioning of frameworks, libraries, bundles, and palettes: +#CURRENTLY_ACTIVE_VERSION = YES # Set to "NO" to produce a compatibility binary +#DEPLOY_WITH_VERSION_NAME = A # This should be incremented as your API changes. +#COMPATIBILITY_PROJECT_VERSION = 1 # This should be incremented as your API grows. +#CURRENT_PROJECT_VERSION = 1 # Defaults to using the "vers_string" hack. + +# Some compiler flags can be easily overridden here, but onlytake effect at +# the top-level: +#OPTIMIZATION_CFLAG = -O +#DEBUG_SYMBOLS_CFLAG = -g +#WARNING_CFLAGS = -Wall +#DEBUG_BUILD_CFLAGS = -DDEBUG +#PROFILE_BUILD_CFLAGS = -pg -DPROFILE + +# Flags passed to yacc +#YFLAGS = -d + +# Library and Framework projects only: +# 1. If you want something other than the default .dylib name, override it here +#DYLIB_INSTALL_NAME = lib$(NAME).dylib + +# 2. If you want to change the -install_name flag from the absolute path to the development area, change it here. One good choice is the installation directory. Another one might be none at all. +#DYLIB_INSTALL_DIR = $(INSTALLDIR) + +# Ownership and permissions of files installed by 'install' target +#INSTALL_AS_USER = root # User/group ownership +#INSTALL_AS_GROUP = wheel # (probably want to set both of these) +#INSTALL_PERMISSIONS = # If set, 'install' chmod's executable to this + +# Options to strip for various project types. Note: -S strips debugging symbols +# (executables can be stripped down further with -x or, if they load no bundles, with no +# options at all). +#APP_STRIP_OPTS = -S +#TOOL_STRIP_OPTS = -S +#LIBRARY_STRIP_OPTS = -S # for .a archives +#DYNAMIC_STRIP_OPTS = -S # for bundles and shared libraries +STRIPFLAGS = + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. "Official" +# user-defined rules are: +# * before_install +# * after_install +# * after_installhdrs +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. + diff --git a/ypbind.tproj/Makefile.preamble b/ypbind.tproj/Makefile.preamble new file mode 100644 index 0000000..5ca4df3 --- /dev/null +++ b/ypbind.tproj/Makefile.preamble @@ -0,0 +1,129 @@ +############################################################################### +# NeXT Makefile.preamble +# Copyright 1996, NeXT Software, Inc. +# +# This Makefile is used for configuring the standard app makefiles associated +# with ProjectBuilder. +# +# Use this template to set attributes for a project. Each node in a project +# tree of sub-projects, tools, etc. should have its own Makefile.preamble and +# Makefile.postamble. +# +############################################################################### +## Configure the flags passed to $(CC) here. These flags will also be +## inherited by all nested sub-projects and bundles. Put your -I, -D, -U, and +## -L flags in ProjectBuilder's Build Options inspector if at all possible. +## To change the default flags that get passed to ${CC} +## (e.g. change -O to -O2), see Makefile.postamble. + +# Flags passed to compiler (in addition to -g, -O, etc) +OTHER_CFLAGS = +# Flags passed to ld (in addition to -ObjC, etc.) +OTHER_LDFLAGS = +# Flags passed to libtool when building libraries +OTHER_LIBTOOL_FLAGS = +# For ordering named sections on NEXTSTEP (see ld(1)) +SECTORDER_FLAGS = + +# If you do not want any headers exported before compilations begin, +# uncomment the following line. This can be a big time saver. +#SKIP_EXPORTING_HEADERS = YES + +# Stuff related to exporting headers from this project that isn't already +# handled by PB. +OTHER_PUBLIC_HEADERS = +OTHER_PROJECT_HEADERS = +OTHER_PRIVATE_HEADERS = + +# Set these two macros if you want a precomp to be built as part of +# installation. The cc -precomp will be run in the public header directory +# on the specified public header files with the specified additional flags. +PUBLIC_PRECOMPILED_HEADERS = +PUBLIC_PRECOMPILED_HEADERS_CFLAGS = + +# Set this for library projects if you want to publish header files. If your +# app or tool project exports headers Don't +# include $(DSTROOT); this is added for you automatically. +PUBLIC_HEADER_DIR = +PRIVATE_HEADER_DIR = + +# If, in a subproject, you want to append to the parent's PUBLIC_HEADER_DIR# +# (say, to add a subdirectory like "/sys"), you can use: +PUBLIC_HEADER_DIR_SUFFIX = +PRIVATE_HEADER_DIR_SUFFIX = + +# Set this for dynamic library projects on platforms where code which references +# a dynamic library must link against an import library (i.e., Windows NT) +# Don't include $(DSTROOT); this is added for you automatically. +IMPORT_LIBRARY_DIR = + +# Additional (non-localized) resources for this project, which can be generated +OTHER_RESOURCES = + +# Uncomment this to produce a static archive-style (.a) library +#LIBRARY_STYLE = STATIC + +# Set this to YES if you don't want a final libtool call for a library/framework. +BUILD_OFILES_LIST_ONLY = + +# Additional relocatables to be linked into this project +OTHER_OFILES = +# Additional libraries to link against +OTHER_LIBS = +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +OTHER_GENERATED_OFILES = $(VERS_OFILE) + +## Configure how things get built here. Additional dependencies, source files, +## derived files, and build order should be specified here. + +# Other dependencies of this project +OTHER_PRODUCT_DEPENDS = +# Built *before* building subprojects/bundles +OTHER_INITIAL_TARGETS = +# Other source files maintained by .pre/postamble +OTHER_SOURCEFILES = +# Additional files to be removed by `make clean' +OTHER_GARBAGE = + +# Targets to build before installation +OTHER_INSTALL_DEPENDS = + +# More obscure flags you might want to set for pswrap, yacc, lex, etc. +PSWFLAGS = +YFLAGS = +LFLAGS = + +## Delete this line if you want fast and loose cleans that will not remove +## things like precomps and user-defined OTHER_GARBAGE in subprojects. +CLEAN_ALL_SUBPROJECTS = YES + +## Add more obscure source files here to cause them to be automatically +## processed by the appropriate tool. Note that these files should also be +## added to "Supporting Files" in ProjectBuilder. The desired .o files that +## result from these files should also be added to OTHER_OFILES above so they +## will be linked in. + +# .msg files that should have msgwrap run on them +MSGFILES = +# .defs files that should have mig run on them +DEFSFILES = +# .mig files (no .defs files) that should have mig run on them +MIGFILES = +# .x files that should have rpcgen run on them +RPCFILES = yp.x + +## Add additional Help directories here (add them to the project as "Other +## Resources" in Project Builder) so that they will be compressed into .store +## files and copied into the app wrapper. If the help directories themselves +## need to also be in the app wrapper, then a cp command will need to be added +## in an after_install target. +OTHER_HELP_DIRS = + +# After you have saved your project using the 4.0 PB, you will automatically +# start using the makefiles in $(SYSTEM_DEVELOPER_DIR)/Makefiles/project. If you should +# need to revert back to the old 3.3 Makefile behavior, override MAKEFILEDIR to +# be $(SYSTEM_DEVELOPER_DIR)/Makefiles/app. + +# Don't add more rules here unless you want the first one to be the default +# target for make! Put all your targets in Makefile.postamble. diff --git a/ypbind.tproj/PB.project b/ypbind.tproj/PB.project new file mode 100644 index 0000000..dba6980 --- /dev/null +++ b/ypbind.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (ypbind.c); + OTHER_SOURCES = (Makefile, Makefile.dist, Makefile.postamble, Makefile.preamble, yp.x); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypbind; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypbind.tproj/yp.x b/ypbind.tproj/yp.x new file mode 100644 index 0000000..cf2be0c --- /dev/null +++ b/ypbind.tproj/yp.x @@ -0,0 +1,24 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +#include diff --git a/ypbind.tproj/ypbind.c b/ypbind.tproj/ypbind.c new file mode 100644 index 0000000..bad58c0 --- /dev/null +++ b/ypbind.tproj/ypbind.c @@ -0,0 +1,1289 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$Id: ypbind.c,v 1.1.1.1 1999/05/02 03:59:00 wsanchez Exp $"; +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include + +#define _PATH_YPBIND_LOCK "/var/run/ypbind.lock" +#define YPSERVERSSUFF ".ypservers" +#define BINDINGDIR "/var/yp/binding" + +#ifndef O_SHLOCK +#define O_SHLOCK 0 +#endif + +#define BUFSIZE 1400 + +struct _dom_binding +{ + struct _dom_binding *dom_pnext; + char dom_domain[YPMAXDOMAIN + 1]; + struct sockaddr_in dom_server_addr; + unsigned short int dom_server_port; + int dom_socket; + CLIENT *dom_client; + long dom_vers; + time_t dom_check_t; + time_t dom_ask_t; + int dom_lockfd; + int dom_alive; + u_int32_t dom_xid; +}; + +static char *dname; + +static struct _dom_binding *ypbindlist; +static int check; + +typedef enum +{ + YPBIND_DIRECT, + YPBIND_BROADCAST, + YPBIND_SETLOCAL, + YPBIND_SETALL +} ypbind_mode_t; + +ypbind_mode_t ypbindmode; + +/* + * If ypbindmode is YPBIND_SETLOCAL or YPBIND_SETALL, this indicates + * whether or not we've been "ypset". If we haven't, we behave like + * YPBIND_BROADCAST. If we have, we behave like YPBIND_DIRECT. + */ +int been_ypset; + +static int insecure; +static int rpcsock, pingsock; +static struct rmtcallargs rmtca; +static struct rmtcallres rmtcr; +static bool_t rmtcr_outval; +static u_long rmtcr_port; +static SVCXPRT *udptransp, *tcptransp; + +int main __P((int, char *[])); + +static void usage __P((void)); +static struct _dom_binding *makebinding __P((const char *)); +static int makelock __P((struct _dom_binding *)); +static void removelock __P((struct _dom_binding *)); +static void checkwork __P((void)); +static int ping __P((struct _dom_binding *)); +static int nag_servers __P((struct _dom_binding *)); +static enum clnt_stat handle_replies __P((void)); +static enum clnt_stat handle_ping __P((void)); +static void rpc_received __P((char *, struct sockaddr_in *, int)); +static struct _dom_binding *xid2ypdb __P((u_int32_t)); +static u_int32_t unique_xid __P((struct _dom_binding *)); +static int broadcast __P((char *, int)); +static int direct __P((char *, int)); +static int direct_set __P((char *, int, struct _dom_binding *)); + +#define DEBUG_NONE 0 +#define DEBUG_STDERR 1 +#define DEBUG_SYSLOG 2 + +static int debug; +static char *msg_str = NULL; + +void +sys_openlog(int debug, char *str, int flags, int facility) +{ + if (msg_str != NULL) free(msg_str); + msg_str = NULL; + if (str != NULL) + { + msg_str = malloc(strlen(str) + 1); + strcpy(msg_str, str); + } + + if (debug & DEBUG_SYSLOG) openlog(msg_str, flags, facility); +} + +void +sys_msg(int debug, int priority, char *message, ...) +{ + va_list ap; + + va_start(ap, message); + + if (debug & DEBUG_SYSLOG) vsyslog(priority, message, ap); + + if (debug & DEBUG_STDERR) + { + if (msg_str != NULL) fprintf(stderr, "%s: ", msg_str); + vfprintf(stderr, message, ap); + fprintf(stderr, "\n"); + fflush(stderr); + } + + va_end(ap); +} + +static void +usage() +{ + fprintf(stderr, + "Usage: ypbind [-broadcast] [-insecure] [-ypset] [-ypsetme] [-d]\n"); + exit(1); +} + +static struct _dom_binding * +makebinding(const char *dm) +{ + struct _dom_binding *ypdb; + + ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); + memset(ypdb, 0, sizeof *ypdb); + strncpy(ypdb->dom_domain, dm, sizeof ypdb->dom_domain); + ypdb->dom_domain[sizeof(ypdb->dom_domain) - 1] = '\0'; + + return ypdb; +} + +static int +makelock(struct _dom_binding *ypdb) +{ + int fd; + char path[MAXPATHLEN]; + + snprintf(path, sizeof(path), "%s/%s.%ld", BINDINGDIR, + ypdb->dom_domain, ypdb->dom_vers); + + fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644); + if (fd == -1) + { + mkdir(BINDINGDIR, 0755); + fd = open(path, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644); + if (fd == -1) return -1; + } + +#if O_SHLOCK == 0 + flock(fd, LOCK_SH); +#endif + return fd; +} + +static void +removelock(struct _dom_binding *ypdb) +{ + char path[MAXPATHLEN]; + + snprintf(path, sizeof(path), "%s/%s.%ld", + BINDINGDIR, ypdb->dom_domain, ypdb->dom_vers); + unlink(path); +} + +static void * +svc_ypbindproc_null_2(void *argp, SVCXPRT *transp) +{ + static char res; + + sys_msg(debug, LOG_DEBUG, "ypbindproc_null_2"); + + memset(&res, 0, sizeof(res)); + return (void *)&res; +} + +static void * +svc_ypbindproc_domain_2(void *argp, SVCXPRT *transp) +{ + static struct ypbind_resp res; + struct _dom_binding *ypdb; + char *arg = *(char **) argp; + int count; + + sys_msg(debug, LOG_DEBUG, "ypbindproc_domain_2 %s", arg); + + memset(&res, 0, sizeof res); + res.ypbind_status = YPBIND_FAIL_VAL; + + for (count = 0, ypdb = ypbindlist; + ypdb != NULL; + ypdb = ypdb->dom_pnext, count++) + { + /* prevent denial of service */ + if (count > 100) return NULL; + if (!strcmp(ypdb->dom_domain, arg)) break; + } + + if (ypdb == NULL) + { + ypdb = makebinding(arg); + ypdb->dom_vers = YPVERS; + ypdb->dom_alive = 0; + ypdb->dom_lockfd = -1; + removelock(ypdb); + ypdb->dom_xid = unique_xid(ypdb); + ypdb->dom_pnext = ypbindlist; + ypbindlist = ypdb; + check++; + sys_msg(debug, LOG_ERR, "unknown domain %s", arg); + return NULL; + } + + if (ypdb->dom_alive == 0) + { + sys_msg(debug, LOG_ERR, "dead domain %s", arg); + return NULL; + } + +#ifdef HEURISTIC + time(&now); + if (now < ypdb->dom_ask_t + 5) + { + /* + * Hmm. More than 2 requests in 5 seconds have indicated + * that my binding is possibly incorrect. + * Ok, do an immediate poll of the server. + */ + if (ypdb->dom_check_t >= now) + { + /* don't flood it */ + ypdb->dom_check_t = 0; + check++; + } + } + ypdb->dom_ask_t = now; +#endif + + res.ypbind_status = YPBIND_SUCC_VAL; + bcopy(&ypdb->dom_server_addr.sin_addr.s_addr, + res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 4); + bcopy(&ypdb->dom_server_port, + res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 2); + + sys_msg(debug, LOG_DEBUG, "domain %s at %s/%d", ypdb->dom_domain, + inet_ntoa(ypdb->dom_server_addr.sin_addr), + ntohs(ypdb->dom_server_addr.sin_port)); + return &res; +} + +static void * +svc_ypbindproc_setdom_2(void *argp, SVCXPRT *transp) +{ + struct ypbind_setdom *sd = argp; + struct sockaddr_in *fromsin, bindsin; + static bool_t res; + + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bcopy(&sd->ypsetdom_binding.ypbind_binding_addr, + &bindsin.sin_addr.s_addr, 4); + bcopy(&sd->ypsetdom_binding.ypbind_binding_port, + &bindsin.sin_port, 2); + fromsin = svc_getcaller(transp); + + memset(&res, 0, sizeof(res)); + + switch (ypbindmode) + { + case YPBIND_SETLOCAL: + if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) + { + sys_msg(debug, LOG_ERR, "ypset from %s denied", + inet_ntoa(fromsin->sin_addr)); + return NULL; + } + + /* FALLTHROUGH */ + + case YPBIND_SETALL: + been_ypset = 1; + break; + + case YPBIND_DIRECT: + case YPBIND_BROADCAST: + default: + sys_msg(debug, LOG_ERR, "ypset denied"); + return NULL; + } + + if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) + { + sys_msg(debug, LOG_ERR, "ypset from unpriviledged port denied"); + return &res; + } + + if (sd->ypsetdom_vers != YPVERS) + { + sys_msg(debug, LOG_ERR, "ypset with wrong version denied"); + sys_msg(debug, LOG_DEBUG, "ypsetdom_vers = %lu YPVERS = %lu", + sd->ypsetdom_vers, YPVERS); + return &res; + } + + rpc_received(sd->ypsetdom_domain, &bindsin, 1); + + sys_msg(debug, LOG_DEBUG, "ypset to %s succeeded", + inet_ntoa(bindsin.sin_addr)); + res = 1; + return &res; +} + +static void +ypbindprog_2(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union + { + char ypbindproc_domain_2_arg[YPMAXDOMAIN + 1]; + struct ypbind_setdom ypbindproc_setdom_2_arg; + } argument; + struct authunix_parms *creds; + char *result; + xdrproc_t xdr_argument, xdr_result; + void *(*local) __P((void *, SVCXPRT *)); + + switch (rqstp->rq_proc) + { + case YPBINDPROC_NULL: + xdr_argument = xdr_void; + xdr_result = xdr_void; + local = svc_ypbindproc_null_2; + break; + + case YPBINDPROC_DOMAIN: + xdr_argument = xdr_domainname; + xdr_result = xdr_ypbind_resp; + local = svc_ypbindproc_domain_2; + break; + + case YPBINDPROC_SETDOM: + switch (rqstp->rq_cred.oa_flavor) + { + case AUTH_UNIX: + creds = (struct authunix_parms *)rqstp->rq_clntcred; + if (creds->aup_uid != 0) + { + svcerr_auth(transp, AUTH_BADCRED); + return; + } + break; + + default: + svcerr_auth(transp, AUTH_TOOWEAK); + return; + } + + xdr_argument = xdr_ypbind_setdom; + xdr_result = xdr_void; + local = svc_ypbindproc_setdom_2; + break; + + default: + svcerr_noproc(transp); + return; + } + + memset(&argument, 0, sizeof(argument)); + if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) + { + svcerr_decode(transp); + return; + } + + result = (*local)(&argument, transp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) + { + svcerr_systemerr(transp); + } + + return; +} + +int +main(int argc, char *argv[]) +{ + struct timeval tv; + fd_set fdsr; + int width, lockfd; + int evil = 0, one, i; + char pathname[MAXPATHLEN]; + struct stat st; + + yp_get_default_domain(&dname); + if (dname[0] == '\0') + { + fprintf(stderr, "Domainname not set. Aborting.\n"); + exit(1); + } + + debug = DEBUG_SYSLOG; + ypbindmode = YPBIND_DIRECT; + for (i = 1; i < argc; i++) + { + if (!strcmp(argv[i], "-insecure")) + insecure = 1; + + else if (!strcmp(argv[i], "-ypset")) + ypbindmode = YPBIND_SETALL; + + else if (!strcmp(argv[i], "-ypsetme")) + ypbindmode = YPBIND_SETLOCAL; + + else if (!strcmp(argv[i], "-broadcast")) + ypbindmode = YPBIND_BROADCAST; + + else if (!strcmp(argv[i], "-d")) + debug = DEBUG_STDERR; + + else + usage(); + } + + sys_openlog(debug, "ypbind", LOG_NDELAY | LOG_PID, LOG_DAEMON); + + /* + * Per traditional ypbind(8) semantics, if a ypservers + * file does not exist, we default to broadcast mode. + * If the file does exist, we default to direct mode. + * Note that we can still override direct mode by passing + * the -broadcast flag. + */ + snprintf(pathname, sizeof(pathname), "%s/%s%s", + BINDINGDIR, dname, YPSERVERSSUFF); + + if ((ypbindmode == YPBIND_DIRECT) && (stat(pathname, &st) < 0)) + { + sys_msg(debug, LOG_DEBUG, "%s does not exist, defaulting to broadcast.", + pathname); + ypbindmode = YPBIND_BROADCAST; + } + + /* blow away everything in BINDINGDIR */ + + lockfd = open(_PATH_YPBIND_LOCK, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644); + if (lockfd == -1) + { + sys_msg(debug, LOG_ERR, "Cannot create %s", _PATH_YPBIND_LOCK); + exit(1); + } + +#if O_SHLOCK == 0 + flock(lockfd, LOCK_SH); +#endif + + pmap_unset(YPBINDPROG, YPBINDVERS); + + udptransp = svcudp_create(RPC_ANYSOCK); + if (udptransp == NULL) + { + sys_msg(debug, LOG_ERR, "Cannot create udp service."); + exit(1); + } + + if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, + IPPROTO_UDP)) + { + sys_msg(debug, LOG_ERR, + "Unable to register (YPBINDPROG, YPBINDVERS, udp)."); + exit(1); + } + + tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); + if (tcptransp == NULL) + { + sys_msg(debug, LOG_ERR, "Cannot create tcp service."); + exit(1); + } + + if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, + IPPROTO_TCP)) + { + sys_msg(debug, LOG_ERR, + "Unable to register (YPBINDPROG, YPBINDVERS, tcp)."); + exit(1); + } + + /* XXX use SOCK_STREAM for direct queries? */ + rpcsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (rpcsock == -1) + { + sys_msg(debug, LOG_ERR, "rpc socket() failed."); + exit(1); + } + + pingsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (pingsock == -1) + { + sys_msg(debug, LOG_ERR, "ping socket() failed."); + exit(1); + } + + fcntl(rpcsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY); + fcntl(pingsock, F_SETFL, fcntl(pingsock, F_GETFL, 0) | FNDELAY); + + one = 1; + setsockopt(rpcsock, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)); + rmtca.prog = YPPROG; + rmtca.vers = YPVERS; + rmtca.proc = YPPROC_DOMAIN_NONACK; + rmtca.xdr_args = NULL; /* set at call time */ + rmtca.args_ptr = NULL; /* set at call time */ + rmtcr.port_ptr = &rmtcr_port; + rmtcr.xdr_results = xdr_bool; + rmtcr.results_ptr = (caddr_t)&rmtcr_outval; + + /* build initial domain binding, make it "unsuccessful" */ + ypbindlist = makebinding(dname); + ypbindlist->dom_vers = YPVERS; + ypbindlist->dom_alive = 0; + ypbindlist->dom_lockfd = -1; + removelock(ypbindlist); + + checkwork(); + +// width = svc_maxfd; + width = FD_SETSIZE; + width = 32; + if (rpcsock > width) + width = rpcsock; + if (pingsock > width) + width = pingsock; + width++; + + for (;;) + { + fdsr = svc_fdset; + FD_SET(rpcsock, &fdsr); + FD_SET(pingsock, &fdsr); + tv.tv_sec = 1; + tv.tv_usec = 0; + + switch (select(width, &fdsr, NULL, NULL, &tv)) + { + case 0: + checkwork(); + break; + + case -1: + sys_msg(debug, LOG_WARNING, "select: %s", strerror(errno)); + break; + + default: + if (FD_ISSET(rpcsock, &fdsr)) handle_replies(); + if (FD_ISSET(pingsock, &fdsr)) handle_ping(); + svc_getreqset(&fdsr); + if (check) checkwork(); + break; + } + + if ((evil == 0) && (ypbindlist->dom_alive != 0)) + { + evil = 1; + if (debug == DEBUG_SYSLOG) daemon(0, 0); + } + } +} + +/* + * State transition is done like this: + * + * STATE EVENT ACTION NEWSTATE TIMEOUT + * no binding timeout broadcast no binding 5 sec + * no binding answer -- binding 60 sec + * binding timeout ping server checking 5 sec + * checking timeout ping server + broadcast checking 5 sec + * checking answer -- binding 60 sec + */ +void +checkwork() +{ + struct _dom_binding *ypdb; + time_t t; + + check = 0; + + time(&t); + for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) + { + if (ypdb->dom_check_t < t) + { + if (ypdb->dom_alive == 1) ping(ypdb); + else nag_servers(ypdb); + time(&t); + ypdb->dom_check_t = t + 5; + } + } +} + +int +ping(struct _dom_binding *ypdb) +{ + char *dom = ypdb->dom_domain; + struct rpc_msg msg; + char buf[BUFSIZE]; + enum clnt_stat st; + int outlen; + AUTH *rpcua; + XDR xdr; + + memset(&xdr, 0, sizeof xdr); + memset(&msg, 0, sizeof msg); + + rpcua = authunix_create_default(); + if (rpcua == NULL) + { + sys_msg(debug, LOG_ERR, "ping: cannot get unix auth"); + return RPC_SYSTEMERROR; + } + + msg.rm_direction = CALL; + msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + msg.rm_call.cb_prog = YPPROG; + msg.rm_call.cb_vers = YPVERS; + msg.rm_call.cb_proc = YPPROC_DOMAIN_NONACK; + msg.rm_call.cb_cred = rpcua->ah_cred; + msg.rm_call.cb_verf = rpcua->ah_verf; + + msg.rm_xid = ypdb->dom_xid; + xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE); + if (!xdr_callmsg(&xdr, &msg)) + { + st = RPC_CANTENCODEARGS; + AUTH_DESTROY(rpcua); + return st; + } + + if (!xdr_domainname(&xdr, (void *)&dom)) + { + st = RPC_CANTENCODEARGS; + AUTH_DESTROY(rpcua); + return st; + } + + outlen = (int)xdr_getpos(&xdr); + xdr_destroy(&xdr); + if (outlen < 1) + { + st = RPC_CANTENCODEARGS; + AUTH_DESTROY(rpcua); + return st; + } + + AUTH_DESTROY(rpcua); + + ypdb->dom_alive = 2; + if (sendto(pingsock, buf, outlen, 0, + (struct sockaddr *)&ypdb->dom_server_addr, + sizeof ypdb->dom_server_addr) == -1) + sys_msg(debug, LOG_WARNING, "ping: sendto"); + return 0; + +} + +static int +nag_servers(struct _dom_binding *ypdb) +{ + char *dom = ypdb->dom_domain; + struct rpc_msg msg; + char buf[BUFSIZE]; + enum clnt_stat st; + int outlen; + AUTH *rpcua; + XDR xdr; + + rmtca.xdr_args = xdr_domainname; + rmtca.args_ptr = (char *)&dom; + + memset(&xdr, 0, sizeof xdr); + memset(&msg, 0, sizeof msg); + + rpcua = authunix_create_default(); + if (rpcua == NULL) + { + sys_msg(debug, LOG_ERR, "ping: cannot get unix auth"); + return RPC_SYSTEMERROR; + } + + msg.rm_direction = CALL; + msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; + msg.rm_call.cb_prog = PMAPPROG; + msg.rm_call.cb_vers = PMAPVERS; + msg.rm_call.cb_proc = PMAPPROC_CALLIT; + msg.rm_call.cb_cred = rpcua->ah_cred; + msg.rm_call.cb_verf = rpcua->ah_verf; + + msg.rm_xid = ypdb->dom_xid; + xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE); + if (!xdr_callmsg(&xdr, &msg)) + { + st = RPC_CANTENCODEARGS; + AUTH_DESTROY(rpcua); + return st; + } + + if (!xdr_rmtcall_args(&xdr, &rmtca)) + { + st = RPC_CANTENCODEARGS; + AUTH_DESTROY(rpcua); + return st; + } + + outlen = (int)xdr_getpos(&xdr); + xdr_destroy(&xdr); + if (outlen < 1) + { + st = RPC_CANTENCODEARGS; + AUTH_DESTROY(rpcua); + return st; + } + + AUTH_DESTROY(rpcua); + + if (ypdb->dom_lockfd != -1) + { + close(ypdb->dom_lockfd); + ypdb->dom_lockfd = -1; + removelock(ypdb); + } + + if (ypdb->dom_alive == 2) + { + /* + * This resolves the following situation: + * ypserver on other subnet was once bound, + * but rebooted and is now using a different port + */ + struct sockaddr_in bindsin; + + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bindsin.sin_port = htons(PMAPPORT); + bindsin.sin_addr = ypdb->dom_server_addr.sin_addr; + + if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin, + sizeof bindsin) == -1) + sys_msg(debug, LOG_WARNING, "broadcast: sendto"); + } + + switch (ypbindmode) + { + case YPBIND_SETALL: + case YPBIND_SETLOCAL: + if (been_ypset) return direct_set(buf, outlen, ypdb); + /* FALLTHROUGH */ + + case YPBIND_BROADCAST: + return broadcast(buf, outlen); + + case YPBIND_DIRECT: + return direct(buf, outlen); + } + + return -1; +} + +static int +broadcast(char *buf, int outlen) +{ + struct ifconf ifc; + struct ifreq *ifr; + int offset, addrlen; + struct in_addr in; + int sock; + char inbuf[8192]; + struct sockaddr_in bindsin; + + /* find all networks and send the RPC packet out them all */ + sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock == -1) + { + sys_msg(debug, LOG_WARNING, "broadcast: socket: %s", strerror(errno)); + return -1; + } + + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bindsin.sin_port = htons(PMAPPORT); + + ifc.ifc_len = sizeof inbuf; + ifc.ifc_buf = inbuf; + if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) + { + close(sock); + sys_msg(debug, LOG_WARNING, "broadcast: ioctl(SIOCGIFCONF): %s", + strerror(errno)); + return -1; + } + + addrlen = sizeof(struct ifreq) - IFNAMSIZ; + offset = 0; + + while (offset <= ifc.ifc_len) + { + ifr = (struct ifreq *)(ifc.ifc_buf + offset); + offset += IFNAMSIZ; + if (ifr->ifr_addr.sa_len > addrlen) offset += ifr->ifr_addr.sa_len; + else offset += addrlen; + + if (ifr->ifr_addr.sa_family != AF_INET) continue; + if (ioctl(sock, SIOCGIFFLAGS, ifr) < 0) continue; + if ((ifr->ifr_flags & IFF_UP) == 0) continue; + + if (ifr->ifr_flags & IFF_BROADCAST) + { + if (ioctl(sock, SIOCGIFBRDADDR, ifr) < 0) + { + sys_msg(debug, LOG_WARNING, + "broadcast: ioctl(SIOCGIFBRDADDR): %s", strerror(errno)); + continue; + } + } + else if (ifr->ifr_flags & IFF_LOOPBACK) + { + if (ioctl(sock, SIOCGIFADDR, ifr) < 0) + { + sys_msg(debug, LOG_WARNING, + "broadcast: ioctl(SIOCGIFADDR): %s", strerror(errno)); + continue; + } + } + else continue; + + in = ((struct sockaddr_in *)&(ifr->ifr_addr))->sin_addr; + bindsin.sin_addr = in; + if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin, + sizeof bindsin) == -1) + sys_msg(debug, LOG_WARNING, "broadcast: sendto: %s", + strerror(errno)); + } + + close(sock); + return 0; +} + +static int +direct(char *buf, int outlen) +{ + static FILE *df; + static char ypservers_path[MAXPATHLEN]; + char line[_POSIX2_LINE_MAX]; + char *p; + struct hostent *hp; + struct sockaddr_in bindsin; + int i, count = 0; + + if (df) rewind(df); + else { + snprintf(ypservers_path, sizeof(ypservers_path), + "%s/%s%s", BINDINGDIR, dname, YPSERVERSSUFF); + df = fopen(ypservers_path, "r"); + if (df == NULL) + { + sys_msg(debug, LOG_ALERT, "Missing file %s, aborting.", + ypservers_path); + exit(1); + } + } + + memset(&bindsin, 0, sizeof bindsin); + bindsin.sin_family = AF_INET; + bindsin.sin_len = sizeof(bindsin); + bindsin.sin_port = htons(PMAPPORT); + + while(fgets(line, sizeof(line), df) != NULL) + { + /* skip lines that are too big */ + p = strchr(line, '\n'); + if (p == NULL) + { + int c; + + while ((c = getc(df)) != '\n' && c != EOF); + continue; + } + + *p = '\0'; + p = line; + while (isspace(*p)) p++; + if (*p == '#') continue; + hp = gethostbyname(p); + if (hp == NULL) + { + sys_msg(debug, LOG_ERR, "Can't find host: %s", p); + continue; + } + + /* step through all addresses in case first is unavailable */ + for (i = 0; hp->h_addr_list[i]; i++) + { + memmove(&bindsin.sin_addr, hp->h_addr_list[0], + hp->h_length); + if (sendto(rpcsock, buf, outlen, 0, + (struct sockaddr *)&bindsin, sizeof bindsin) < 0) + { + sys_msg(debug, LOG_WARNING, "direct: sendto: %s", + strerror(errno)); + continue; + } + else count++; + } + } + + if (count == 0) + { + sys_msg(debug, LOG_ALERT, + "Can't contact any servers listed in %s. Aborting", ypservers_path); + exit(1); + } + + return 0; +} + +static int +direct_set(char *buf, int outlen, struct _dom_binding *ypdb) +{ + struct sockaddr_in bindsin; + char path[MAXPATHLEN]; + struct iovec iov[2]; + struct ypbind_resp ybr; + SVCXPRT dummy_svc; + int fd, bytes; + + /* + * Gack, we lose if binding file went away. We reset + * "been_set" if this happens, otherwise we'll never + * bind again. + */ + snprintf(path, sizeof(path), "%s/%s.%ld", BINDINGDIR, + ypdb->dom_domain, ypdb->dom_vers); + + if ((fd = open(path, O_SHLOCK|O_RDONLY, 0644)) == -1) + { + sys_msg(debug, LOG_WARNING, "Can't open file %s", path); + been_ypset = 0; + return -1; + } + +#if O_SHLOCK == 0 + flock(fd, LOCK_SH); +#endif + + /* Read the binding file... */ + iov[0].iov_base = (caddr_t)&(dummy_svc.xp_port); + iov[0].iov_len = sizeof(dummy_svc.xp_port); + iov[1].iov_base = (caddr_t)&ybr; + iov[1].iov_len = sizeof(ybr); + bytes = readv(fd, iov, 2); + close(fd); + + if (bytes != (iov[0].iov_len + iov[1].iov_len)) + { + /* Binding file corrupt? */ + sys_msg(debug, LOG_WARNING, "Can't parse file %s", path); + been_ypset = 0; + return -1; + } + + bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, + &bindsin.sin_addr, 4); + + if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin, + sizeof(bindsin)) < 0) + { + sys_msg(debug, LOG_WARNING, "direct_set: sendto: %s", strerror(errno)); + return -1; + } + + return 0; +} + +static enum clnt_stat +handle_replies() +{ + char buf[BUFSIZE]; + int fromlen, inlen; + struct _dom_binding *ypdb; + struct sockaddr_in raddr; + struct rpc_msg msg; + XDR xdr; + +recv_again: + memset(&xdr, 0, sizeof(xdr)); + memset(&msg, 0, sizeof(msg)); + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = (caddr_t)&rmtcr; + msg.acpted_rply.ar_results.proc = xdr_rmtcallres; + +try_again: + fromlen = sizeof (struct sockaddr); + inlen = recvfrom(rpcsock, buf, sizeof buf, 0, + (struct sockaddr *)&raddr, &fromlen); + if (inlen < 0) + { + if (errno == EINTR) goto try_again; + return RPC_CANTRECV; + } + + if (inlen < sizeof(u_int32_t)) goto recv_again; + + /* + * see if reply transaction id matches sent id. + * If so, decode the results. + */ + xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE); + if (xdr_replymsg(&xdr, &msg)) + { + if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) { + raddr.sin_port = htons((u_short)rmtcr_port); + ypdb = xid2ypdb(msg.rm_xid); + if (ypdb != NULL) rpc_received(ypdb->dom_domain, &raddr, 0); + } + } + + xdr.x_op = XDR_FREE; + msg.acpted_rply.ar_results.proc = xdr_void; + xdr_destroy(&xdr); + + return RPC_SUCCESS; +} + +static enum clnt_stat +handle_ping() +{ + char buf[BUFSIZE]; + int fromlen, inlen; + struct _dom_binding *ypdb; + struct sockaddr_in raddr; + struct rpc_msg msg; + XDR xdr; + bool_t res; + +recv_again: + memset(&xdr, 0, sizeof(xdr)); + memset(&msg, 0, sizeof(msg)); + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = (caddr_t)&res; + msg.acpted_rply.ar_results.proc = xdr_bool; + +try_again: + fromlen = sizeof (struct sockaddr); + inlen = recvfrom(pingsock, buf, sizeof buf, 0, + (struct sockaddr *)&raddr, &fromlen); + if (inlen < 0) + { + if (errno == EINTR) goto try_again; + return RPC_CANTRECV; + } + + if (inlen < sizeof(u_int32_t)) goto recv_again; + + /* + * see if reply transaction id matches sent id. + * If so, decode the results. + */ + xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE); + if (xdr_replymsg(&xdr, &msg)) + { + if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) + { + ypdb = xid2ypdb(msg.rm_xid); + if (ypdb != NULL) rpc_received(ypdb->dom_domain, &raddr, 0); + } + } + + xdr.x_op = XDR_FREE; + msg.acpted_rply.ar_results.proc = xdr_void; + xdr_destroy(&xdr); + + return RPC_SUCCESS; +} + +/* + * LOOPBACK IS MORE IMPORTANT: PUT IN HACK + */ +void +rpc_received(char *dom, struct sockaddr_in *raddrp, int force) +{ + struct _dom_binding *ypdb; + struct iovec iov[2]; + struct ypbind_resp ybr; + int fd; + + sys_msg(debug, LOG_DEBUG, "returned from %s about %s", + inet_ntoa(raddrp->sin_addr), dom); + + if (dom == NULL) return; + + /* don't support insecure servers by default */ + if (!insecure && ntohs(raddrp->sin_port) >= IPPORT_RESERVED) return; + + for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) + { + if (!strcmp(ypdb->dom_domain, dom)) break; + } + + if (ypdb == NULL) + { + if (force == 0) return; + ypdb = makebinding(dom); + ypdb->dom_lockfd = -1; + ypdb->dom_pnext = ypbindlist; + ypbindlist = ypdb; + } + + /* soft update, alive */ + if (ypdb->dom_alive == 1 && force == 0) + { + if (!memcmp(&ypdb->dom_server_addr, raddrp, + sizeof ypdb->dom_server_addr)) + { + ypdb->dom_alive = 1; + /* recheck binding in 60 sec */ + ypdb->dom_check_t = time(NULL) + 60; + } + return; + } + + memcpy(&ypdb->dom_server_addr, raddrp, sizeof ypdb->dom_server_addr); + /* recheck binding in 60 seconds */ + ypdb->dom_check_t = time(NULL) + 60; + ypdb->dom_vers = YPVERS; + ypdb->dom_alive = 1; + + if (ypdb->dom_lockfd != -1) close(ypdb->dom_lockfd); + + if ((fd = makelock(ypdb)) == -1) return; + + /* + * ok, if BINDINGDIR exists, and we can create the binding file, + * then write to it.. + */ + ypdb->dom_lockfd = fd; + + iov[0].iov_base = (caddr_t)&(udptransp->xp_port); + iov[0].iov_len = sizeof udptransp->xp_port; + iov[1].iov_base = (caddr_t)&ybr; + iov[1].iov_len = sizeof ybr; + + memset(&ybr, 0, sizeof ybr); + ybr.ypbind_status = YPBIND_SUCC_VAL; + bcopy(&raddrp->sin_addr.s_addr, + ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 4); + bcopy(&raddrp->sin_port, + ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, 2); + + if (writev(ypdb->dom_lockfd, iov, 2) != + iov[0].iov_len + iov[1].iov_len) + { + sys_msg(debug, LOG_WARNING, "writev: %s", strerror(errno)); + close(ypdb->dom_lockfd); + removelock(ypdb); + ypdb->dom_lockfd = -1; + } +} + +static struct _dom_binding * +xid2ypdb(u_int32_t xid) +{ + struct _dom_binding *ypdb; + + for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) + { + if (ypdb->dom_xid == xid) break; + } + + return (ypdb); +} + +static u_int32_t +unique_xid(struct _dom_binding *ypdb) +{ + u_int32_t tmp_xid; + + tmp_xid = (u_int32_t)(((u_long)ypdb) & 0xffffffff); + while (xid2ypdb(tmp_xid) != NULL) tmp_xid++; + + return tmp_xid; +} diff --git a/ypcat.tproj/Makefile b/ypcat.tproj/Makefile new file mode 100644 index 0000000..e3a8242 --- /dev/null +++ b/ypcat.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypcat + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ypcat.c + +OTHERSRCS = Makefile.dist Makefile.preamble ypcat.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypcat.tproj/Makefile.dist b/ypcat.tproj/Makefile.dist new file mode 100644 index 0000000..55b8f72 --- /dev/null +++ b/ypcat.tproj/Makefile.dist @@ -0,0 +1,6 @@ +# from: @(#)Makefile 5.8 (Berkeley) 7/28/90 +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $ + +PROG= ypcat + +.include diff --git a/ypcat.tproj/Makefile.preamble b/ypcat.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/ypcat.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/ypcat.tproj/PB.project b/ypcat.tproj/PB.project new file mode 100644 index 0000000..fc90efc --- /dev/null +++ b/ypcat.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (ypcat.c); + OTHER_SOURCES = (Makefile.dist, Makefile.preamble, ypcat.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypcat; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypcat.tproj/ypcat.1 b/ypcat.tproj/ypcat.1 new file mode 100644 index 0000000..529b3ee --- /dev/null +++ b/ypcat.tproj/ypcat.1 @@ -0,0 +1,70 @@ +.\" Copyright (c) 1993 Winning Strategies, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Winning Strategies, Inc. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: ypcat.1,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $ +.\" +.Dd December 3, 1993 +.Dt YPCAT 1 +.Os +.Sh NAME +.Nm ypcat +.Nd "print the values of all keys in a YP database" +.Sh SYNOPSIS +.Nm ypcat +.Op Fl kt +.Op Fl d Ar domainname +.Ar mapname +.Nm ypcat +.Fl x +.Sh DESCRIPTION +.Nm Ypcat +prints out the values of all keys from the +.Tn YP +database specified by +.Ar mapname, +which may be a map name or a map nickname. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar domainname +Specify a domain other than the default domain. +.It Fl k +Display map keys. +This option is useful with maps in which the values are null or the key +is not part of the value. +.It Fl t +Inhibit translation of map nicknames +to their corresponding map names. +.It Fl x +Display the map nickname table. +.El +.Sh SEE ALSO +.Xr ypmatch 1 , +.Xr yp 8 +.Sh AUTHOR +Theo De Raadt diff --git a/ypcat.tproj/ypcat.c b/ypcat.tproj/ypcat.c new file mode 100644 index 0000000..72e4e45 --- /dev/null +++ b/ypcat.tproj/ypcat.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$Id: ypcat.c,v 1.1.1.1 1999/05/02 03:59:01 wsanchez Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct ypalias { + char *alias, *name; +} ypaliases[] = { + { "passwd", "passwd.byname" }, + { "group", "group.byname" }, + { "networks", "networks.byaddr" }, + { "hosts", "hosts.byaddr" }, + { "protocols", "protocols.bynumber" }, + { "services", "services.byname" }, + { "aliases", "mail.aliases" }, + { "ethers", "ethers.byname" }, +}; + +int key; + +usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\typcat [-k] [-d domainname] [-t] mapname\n"); + fprintf(stderr, "\typcat -x\n"); + exit(1); +} + +printit(instatus, inkey, inkeylen, inval, invallen, indata) +int instatus; +char *inkey; +int inkeylen; +char *inval; +int invallen; +char *indata; +{ + if(instatus != YP_TRUE) + return instatus; + if(key) + printf("%*.*s ", inkeylen, inkeylen, inkey); + printf("%*.*s\n", invallen, invallen, inval); + return 0; +} + +int +main(argc, argv) +char **argv; +{ + char *domainname; + struct ypall_callback ypcb; + char *inmap; + extern char *optarg; + extern int optind; + int notrans; + int c, r, i; + + notrans = key = 0; + yp_get_default_domain(&domainname); + + while( (c=getopt(argc, argv, "xd:kt")) != -1) + switch(c) { + case 'x': + for(i=0; i) ]; then \ + if [ ! $(UNSECURE) ]; then \ + $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 | \ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$1, $$1":*:"$$3":"$$4":"$$5":"$$6":"$$7 }' -|\ + $(MAKEDBM) - passwd.byname; \ + $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 |\ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$3, $$1":*:"$$3":"$$4":"$$5":"$$6":"$$7 }' -|\ + $(MAKEDBM) - passwd.byuid; \ + else \ + $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 | \ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$1, $$0 }' - | $(MAKEDBM) - passwd.byname; \ + $(CAT) $(>) | $(CUT) -d: -f1-4,8-10 |\ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$3, $$0 }' - | $(MAKEDBM) - passwd.byuid; \ + fi; \ + $(CAT) $(>) | \ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$1, $$0 }' - | $(MAKEDBM-S) - master.passwd.byname; \ + $(CAT) $(>) | \ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$3, $$0 }' - | $(MAKEDBM-S) - master.passwd.byuid; \ + $(TOUCH) $(@); \ + $(ECHO) "updated passwd"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) passwd.byname; \ + $(YPPUSH) -d $(DOMAIN) passwd.byuid; \ + $(YPPUSH) -d $(DOMAIN) master.passwd.byname; \ + $(YPPUSH) -d $(DOMAIN) master.passwd.byuid; \ + $(ECHO) "pushed passwd"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + +group.time: $(DIR)/group + -@if [ -f $(>) ]; then \ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$1, $$0 }' $(>) | \ + $(MAKEDBM) - group.byname; \ + $(AWK) 'BEGIN { FS=":"; OFS="\t"; } /^[a-zA-Z0-9_]/ \ + { print $$3, $$0 }' $(>) | \ + $(MAKEDBM) - group.bygid; \ + $(TOUCH) $(@); \ + $(ECHO) "updated group"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) group.byname; \ + $(YPPUSH) -d $(DOMAIN) group.bygid; \ + $(ECHO) "pushed group"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + +hosts.time: $(DIR)/hosts + -@if [ -f $(DIR)/hosts ]; then \ + $(STDHOSTS) $(>) | $(SED) -e s/#.*$$// | \ + $(AWK) '{for (i = 2; i <= NF; i++) print $$i, $$0 }' | \ + $(MAKEDBM) - hosts.byname; \ + $(STDHOSTS) $(>) | \ + $(AWK) 'BEGIN { OFS="\t"; } { print $$1, $$0 }' | \ + $(MAKEDBM) - hosts.byaddr; \ + $(TOUCH) $(@); \ + $(ECHO) "updated hosts"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) hosts.byname; \ + $(YPPUSH) -d $(DOMAIN) hosts.byaddr; \ + $(ECHO) "pushed hosts"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + +ethers.time: $(DIR)/ethers + -@if [ -f $(DIR)/ethers ]; then \ + $(STDETHERS) $(>) | $(SED) -e s/#.*$$// | \ + $(AWK) 'BEGIN { FS="\t"; OFS="\t"; } { print $$1, $$0 }' | \ + $(MAKEDBM) - ethers.byaddr; \ + $(STDETHERS) $(>) | \ + $(AWK) 'BEGIN { FS="\t"; OFS="\t"; } { print $$2, $$0 }' | \ + $(MAKEDBM) - ethers.byname; \ + $(TOUCH) $(@); \ + $(ECHO) "updated ethers"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) ethers.byaddr; \ + $(YPPUSH) -d $(DOMAIN) ethers.byname; \ + $(ECHO) "pushed ethers"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + +networks.time: $(DIR)/networks + -@if [ -f $(>) ]; then \ + $(SED) -e "/^#/d" -e s/#.*$$// $(>) | \ + $(AWK) '{print $$1, $$0; for (i = 3;i <= NF;i++) print $$i,$$0}' | \ + $(MAKEDBM) - networks.byname; \ + $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \ + $(MAKEDBM) - networks.byaddr; \ + $(TOUCH) $(@); \ + $(ECHO) "updated networks"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) networks.byname; \ + $(YPPUSH) -d $(DOMAIN) networks.byaddr; \ + $(ECHO) "pushed networks"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + +rpc.time: $(DIR)/rpc + -@if [ -f $(>) ]; then \ + $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \ + $(MAKEDBM) - rpc.bynumber; \ + $(SED) -e "/^#/d" -e s/#.*$$// $(>) | \ + $(AWK) '{print $$1, $$0; for (i = 3;i <= NF;i++) print $$i,$$0}' | \ + $(MAKEDBM) - rpc.byname; \ + $(TOUCH) $(@); \ + $(ECHO) "updated rpc"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) rpc.bynumber; \ + $(YPPUSH) -d $(DOMAIN) rpc.byname; \ + $(ECHO) "pushed rpc"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + +services.time: $(DIR)/services + -@if [ -f $(>) ]; then \ + $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \ + $(MAKEDBM) - services.byname; \ + $(TOUCH) $(@); \ + $(ECHO) "updated services"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) services.byname; \ + $(ECHO) "pushed services"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + +protocols.time: $(DIR)/protocols + -@if [ -f $(>) ]; then \ + $(AWK) 'BEGIN { OFS="\t"; } $$1 !~ /^#/ { print $$2, $$0 }' $(>) | \ + $(MAKEDBM) - protocols.bynumber; \ + $(SED) -e "/^#/d" -e s/#.*$$// $(>) | \ + $(AWK) '{print $$1, $$0; for (i = 3;i <= NF;i++) print $$i,$$0}' | \ + $(MAKEDBM) - protocols.byname; \ + $(TOUCH) $(@); \ + $(ECHO) "updated protocols"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) protocols.bynumber; \ + $(YPPUSH) -d $(DOMAIN) protocols.byname; \ + $(ECHO) "pushed protocols"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + +netid.time: $(DIR)/passwd $(DIR)/group $(DIR)/hosts $(DIR)/netid + -@$(MKNETID) -q -d $(DOMAIN) -p $(DIR)/passwd -g $(DIR)/group -h $(DIR)/hosts -m $(DIR)/netid | \ + $(MAKEDBM) - netid.byname; \ + $(TOUCH) $(@); \ + $(ECHO) "updated netid"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) netid.byname; \ + $(ECHO) "pushed netid"; \ + else \ + : ; \ + fi + + +netgroup.time: $(DIR)/netgroup + -@if [ -f $(>) ]; then \ + $(CAT) $(>) | $(MAKEDBM) - netgroup; \ + $(CAT) $(>) | $(REVNETGROUP) -u -f - | \ + $(MAKEDBM) - netgroup.byuser; \ + $(CAT) $(>) | $(REVNETGROUP) -h -f - | \ + $(MAKEDBM) - netgroup.byhost; \ + $(TOUCH) $(@); \ + $(ECHO) "updated netgroup"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) netgroup; \ + $(YPPUSH) -d $(DOMAIN) netgroup.byuser; \ + $(YPPUSH) -d $(DOMAIN) netgroup.byhost; \ + $(ECHO) "pushed netgroup"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + +amd.home.time: $(AMDDIR)/amd.home + -@if [ -f $(>) ]; then \ + $(SED) -e "s/#.*$$//" -e "/^$$/d" $(>) | \ + $(AWK) '{ \ + for (i = 1; i <= NF; i++) \ + if (i == NF) { \ + if (substr($$i, length($$i), 1) == "\\") { \ + printf("%s", substr($$i, 1, length($$i) - 1)); \ + } \ + else \ + printf("%s\n", $$i); \ + } \ + else \ + printf("%s ", $$i); \ + }' | \ + $(MAKEDBM) - amd.home; \ + $(TOUCH) $(@); \ + $(ECHO) "updated amd.home"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) amd.home; \ + $(ECHO) "pushed amd.home"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + +aliases.time: $(DIR)/aliases + -@if [ -f $(>) ]; then \ + $(CP) -p $(>) $(DOMAIN)-aliases; \ + $(SENDMAIL) -bi -oA$(PWD)/$(DOMAIN)-aliases; \ + $(MAKEDBM) -U $(DOMAIN)-aliases | $(MAKEDBM) - mail.aliases; \ + $(MKALIAS) mail.aliases mail.byaddr; \ + $(TOUCH) $(@); \ + $(RM) $(DOMAIN)-aliases.db $(DOMAIN)-aliases; \ + $(ECHO) "updated aliases"; \ + if [ ! $(NOPUSH) ]; then \ + $(YPPUSH) -d $(DOMAIN) mail.aliases; \ + $(YPPUSH) -d $(DOMAIN) mail.byaddr; \ + $(ECHO) "pushed aliases"; \ + else \ + : ; \ + fi \ + else \ + $(ECHO) "couldn't find $(>)"; \ + fi + + + +passwd: passwd.time +group: group.time +hosts: hosts.time +ethers: ethers.time +networks: networks.time +rpc: rpc.time +services: services.time +protocols: protocols.time +netid: netid.time +netgroup: netgroup.time +amd.home: amd.home.time +aliases: aliases.time +$(DIR)/passwd: +$(DIR)/group: +$(DIR)/hosts: +$(DIR)/ethers: +$(DIR)/networks: +$(DIR)/rpc: +$(DIR)/services: +$(DIR)/protocols: +$(DIR)/netid: +$(DIR)/master.passwd: +$(DIR)/netgroup: +$(DIR)/aliases: +$(AMDDIR)/amd.home: diff --git a/ypinit.tproj/ypinit.sh b/ypinit.tproj/ypinit.sh new file mode 100644 index 0000000..8c21e36 --- /dev/null +++ b/ypinit.tproj/ypinit.sh @@ -0,0 +1,402 @@ +#!/bin/sh +# $Id: ypinit.sh,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $ +# +# ypinit.sh - setup an master or slave server. +# +DOMAINNAME=/bin/domainname +HOSTNAME=/bin/hostname +YPWHICH=/usr/bin/ypwhich +YPXFR=/usr/sbin/ypxfr +YP_DIR=/var/yp +MAKEDBM=/usr/sbin/makedbm +ERROR_EXISTS="NO" +MAKE=make +umask 077 + +#set -xv + +ERROR=USAGE # assume usage error + +if [ $# -eq 1 ] +then + if [ $1 = "-m" ] # ypinit -m + then + DOMAIN=`${DOMAINNAME}` + SERVERTYPE=MASTER + ERROR= + fi + + if [ $1 = "-u" ] # ypinit -u + then + DOMAIN=`${DOMAINNAME}` + SERVERTYPE=UPDATE + ERROR= + fi +fi + +if [ $# -eq 2 ] +then + if [ $1 = "-m" ] # ypinit -m domainname + then + DOMAIN=${2} + SERVERTYPE=MASTER + ERROR= + fi + + if [ $1 = "-s" ] # ypinit -s master_server + then + DOMAIN=`${DOMAINNAME}` + SERVERTYPE=SLAVE + MASTER=${2} + ERROR= + fi + + if [ $1 = "-u" ] # ypinit -u domainname + then + DOMAIN=${2} + SERVERTYPE=UPDATE + ERROR= + fi +fi + +if [ $# -eq 3 ] +then + if [ $1 = "-s" ] # ypinit -s master_server domainname + then + DOMAIN=${3} + SERVERTYPE=SLAVE + MASTER=${2} + ERROR= + fi +fi + +if [ "${ERROR}" = "USAGE" ]; then + cat << \__usage 1>&2 +usage: ypinit -m [domainname] + ypinit -s master_server [domainname] + ypinit -u [domainname] + +The `-m' flag builds a master YP server, and the `-s' flag builds +a slave YP server. When building a slave YP server, `master_server' +must be an existing, reachable YP server. +The `-u' is for updating the ypservers map on a master server. +__usage + + exit 1 +fi + +# Check if domainname is set, don't accept an empty domainname +if [ -z "${DOMAIN}" ]; then + cat << \__no_domain 1>&2 +The local host's YP domain name has not been set. Please set it with +the domainname(8) command or pass the domain as an argument to ypinit(8). +__no_domain + + exit 1 +fi + +# Check if hostname is set, don't accept an empty hostname +HOST=`${HOSTNAME}` +if [ -z "${HOST}" ]; then + cat << \__no_hostname 1>&2 +The local host's hostname has not been set. Please set it with the +hostname(8) command. +__no_hostname + + exit 1 +fi + +# Check if we have contact with master. +if [ "${SERVERTYPE}" = "SLAVE" ]; +then + COUNT=`${YPWHICH} -d ${DOMAIN} -m 2>/dev/null | grep -i ${MASTER} | wc -l | tr -d " "` + if [ "$COUNT" = "0" ] + then + echo "Can't enumerate maps from ${MASTER}. Please check that it is running." 1>&2 + exit 1 + fi +fi + +# Check if user is root +ID=`id -u` +if [ "${ID}" != "0" ]; then + echo "You have to be the superuser to run this. Please login as root." 1>&2 + exit 1 +fi + +# Check if the YP directory exists. + +if [ ! -d ${YP_DIR} -o -f ${YP_DIR} ] +then + echo "The directory ${YP_DIR} doesn't exist. Restore it from the distribution." 1>&2 + exit 1 + +fi + +echo -n "Server Type: ${SERVERTYPE} Domain: ${DOMAIN}" +if [ "${SERVERTYPE}" = "SLAVE" ]; then + echo -n " Master: ${MASTER}" +fi +echo "" + +if [ "${SERVERTYPE}" != "UPDATE" ]; +then + cat << \__notice1 + +Creating an YP server will require that you answer a few questions. +Questions will all be asked at the beginning of the procedure. + +__notice1 + + echo -n "Do you want this procedure to quit on non-fatal errors? [y/n: n] " + read DOEXIT + + case ${DOEXIT} in + y*|Y*) + ERROR_EXIT="YES" + ;; + + *) ERROR_EXIT="NO" + echo "" + echo "Ok, please remember to go back and redo manually whatever fails." + echo "If you don't, something might not work. " + ;; + esac + + if [ -d "${YP_DIR}/${DOMAIN}" ]; then + echo "" + echo -n "Can we destroy the existing ${YP_DIR}/${DOMAIN} and its contents? [y/n: n] " + read KILL + + ERROR= + case ${KILL} in + y*|Y*) + ERROR="DELETE" + ;; + + *) ERROR= + ;; + esac + + if [ "${ERROR}" = "DELETE" ]; then + if ! rm -rf ${YP_DIR}/${DOMAIN}; then + echo "Can't clean up old directory ${YP_DIR}/${DOMAIN}." 1>&2 + exit 1 + fi + else + echo "OK, please clean it up by hand and start again. Bye" + exit 0 + fi + + fi + + if ! mkdir "${YP_DIR}/${DOMAIN}"; then + echo "Can't make new directory ${YP_DIR}/${DOMAIN}." 1>&2 + exit 1 + fi +fi + +if [ "${SERVERTYPE}" = "MASTER" ]; +then + + if [ ! -f ${YP_DIR}/Makefile ] + then + if [ ! -f ${YP_DIR}/Makefile.main ] + then + echo "Can't find ${YP_DIR}/Makefile.main. " 1>&2 + exit 1 + fi + cp ${YP_DIR}/Makefile.main ${YP_DIR}/Makefile + fi + + SUBDIR=`grep "^SUBDIR=" ${YP_DIR}/Makefile` + + if [ -z "${SUBDIR}" ] + then + echo "Can't find line starting with 'SUBDIR=' in ${YP_DIR}/Makefile. " 1>&2 + exit 1 + fi + + NEWSUBDIR="SUBDIR=" + for DIR in `echo ${SUBDIR} | cut -c8-255`; do + if [ ${DIR} != ${DOMAIN} ]; then + NEWSUBDIR="${NEWSUBDIR} ${DIR}" + fi + done + NEWSUBDIR="${NEWSUBDIR} ${DOMAIN}" + + if [ -f ${YP_DIR}/Makefile.tmp ]; then + rm ${YP_DIR}/Makefile.tmp + fi + + mv ${YP_DIR}/Makefile ${YP_DIR}/Makefile.tmp + sed -e "s/^${SUBDIR}/${NEWSUBDIR}/" ${YP_DIR}/Makefile.tmp > \ + ${YP_DIR}/Makefile + rm ${YP_DIR}/Makefile.tmp + + if [ ! -f ${YP_DIR}/Makefile.yp ]; then + echo "Can't find ${YP_DIR}/Makefile.yp. " 1>&2 + exit 1 + fi + + cp ${YP_DIR}/Makefile.yp ${YP_DIR}/${DOMAIN}/Makefile + +fi + +if [ "${SERVERTYPE}" = "SLAVE" ]; +then + + echo "There will be no further questions. The remainder of the procedure" + echo "should take a few minutes, to copy the databases from ${MASTER}." + + for MAP in `${YPWHICH} -d ${DOMAIN} -m | cut -d\ -f1` + do + echo "Transfering ${MAP}..." + if ! ${YPXFR} -h ${MASTER} -c -d ${DOMAIN} ${MAP}; then + echo "Can't transfer map ${MAP}." 1>&2 + ERROR_EXISTS="YES" + if [ "${ERROR_EXIT}" = "YES" ]; then + exit 1 + fi + fi + done + + echo "" + if [ "${ERROR_EXISTS}" = "YES" ]; then + echo "${HOST} has been setup as an YP slave server with errors. " 1>&2 + echo "Please remember fix any problem that occurred." 1>&2 + else + echo "${HOST} has been setup as an YP slave server without any errors. " + fi + + echo "Don't forget to update map ypservers on ${MASTER}." + exit 0 +fi + +LIST_OK="NO" + +while [ "${LIST_OK}" = "NO" ]; +do + + if [ "${SERVERTYPE}" = "MASTER" ]; + then + HOST_LIST="${HOST}" + echo "" + echo "At this point, we have to construct a list of this domains YP servers." + echo "${HOST} is already known as master server." + echo "Please continue to add any slave servers, one per line. When you are" + echo "done with the list, type a ." + echo " master server : ${HOST}" + fi + + if [ "${SERVERTYPE}" = "UPDATE" ]; + then + HOST_LIST="${HOST}" + NEW_LIST="" + MASTER_NAME="" + SHORT_HOST=`echo ${HOST} | cut -d. -f1` + if [ -f ${YP_DIR}/${DOMAIN}/ypservers.db ]; + then + for srv in `${MAKEDBM} -u ${YP_DIR}/${DOMAIN}/ypservers | grep -v "^YP" | tr "\t" " " | cut -d\ -f1`; + do + short_srv=`echo ${srv} | cut -d. -f1` + if [ "${SHORT_HOST}" != "${short_srv}" ] + then + if [ "${NEW_LIST}" = "" ]; + then + NEW_LIST="${srv}" + else + NEW_LIST="${NEW_LIST} ${srv}" + fi + fi + done; + MASTER_NAME=`${MAKEDBM} -u ${YP_DIR}/${DOMAIN}/ypservers | grep "^YP_MASTER_NAME" | tr "\t" " " | cut -d\ -f2` + fi + echo "" + echo "Update the list of hosts running YP servers in domain ${DOMAIN}." + echo "Master for this domain is ${MASTER_NAME}." + echo "" + echo "First verify old servers, type \\ to remove a server." + echo "Then add new servers, one per line. When done type a ." + echo "" + echo " master server : ${HOST}" + if [ "${NEW_LIST}" != "" ]; then + for node in $NEW_LIST; do + echo -n " verify host : [${node}] " + read verify + if [ "${verify}" != "\\" ]; then + HOST_LIST="${HOST_LIST} ${node}" + fi + done; + fi + fi + + echo -n " next host to add: " + + while read h + do + echo -n " next host to add: " + HOST_LIST="${HOST_LIST} ${h}" + done + + echo "" + echo "The current list of NIS servers looks like this:" + echo "" + + for h in `echo ${HOST_LIST}`; + do + echo ${h} + done + + echo "" + echo -n "Is this correct? [y/n: y] " + read hlist_ok + + case $hlist_ok in + n*) echo "Let's try the whole thing again...";; + N*) echo "Let's try the whole thing again...";; + *) LIST_OK="YES";; + esac + +done + +echo "Building ${YP_DIR}/${DOMAIN}/ypservers..." +for host in ${HOST_LIST}; +do + echo "${host} ${host}" +done | ${MAKEDBM} - ${YP_DIR}/${DOMAIN}/ypservers + +if [ $? -ne 0 ]; then + echo "" 1>&2 + echo "Couldn't build yp data base ${YP_DIR}/${DOMAIN}/ypservers." 1>&2 + ERROR_EXISTS="YES" + if [ "${ERROR_EXIT}" = "YES" ]; then + exit 1 + fi +fi + +if [ "${SERVERTYPE}" = "MASTER" ]; then + + CUR_PWD=`pwd` + cd ${YP_DIR}/${DOMAIN} + echo "Running ${YP_DIR}/${DOMAIN}/Makefile..." + if ! ${MAKE} NOPUSH=1; then + echo "" 1>&2 + echo "Error running Makefile." 1>&2 + ERROR_EXISTS="YES" + if [ "${ERROR_EXIT}" = "YES" ]; then + exit 1 + fi + fi + + cd ${CUR_PWD} + + echo "" + if [ "${ERROR_EXISTS}" = "YES" ]; then + echo "${HOST} has been setup as an YP master server with errors. " 1>&2 + echo "Please remember fix any problem that occurred." 1>&2 + else + echo "${HOST} has been setup as an YP master server without any errors. " + fi + +fi diff --git a/ypmatch.tproj/Makefile b/ypmatch.tproj/Makefile new file mode 100644 index 0000000..283ee4c --- /dev/null +++ b/ypmatch.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypmatch + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ypmatch.c + +OTHERSRCS = Makefile.dist Makefile.preamble ypmatch.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypmatch.tproj/Makefile.dist b/ypmatch.tproj/Makefile.dist new file mode 100644 index 0000000..fa9c3ba --- /dev/null +++ b/ypmatch.tproj/Makefile.dist @@ -0,0 +1,6 @@ +# from: @(#)Makefile 5.8 (Berkeley) 7/28/90 +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $ + +PROG= ypmatch + +.include diff --git a/ypmatch.tproj/Makefile.preamble b/ypmatch.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/ypmatch.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/ypmatch.tproj/PB.project b/ypmatch.tproj/PB.project new file mode 100644 index 0000000..2b3516c --- /dev/null +++ b/ypmatch.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (ypmatch.c); + OTHER_SOURCES = (Makefile.dist, Makefile.preamble, ypmatch.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypmatch; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypmatch.tproj/ypmatch.1 b/ypmatch.tproj/ypmatch.1 new file mode 100644 index 0000000..f5e76ec --- /dev/null +++ b/ypmatch.tproj/ypmatch.1 @@ -0,0 +1,71 @@ +.\" Copyright (c) 1993 Winning Strategies, Inc. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Winning Strategies, Inc. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: ypmatch.1,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $ +.\" +.Dd December 3, 1993 +.Dt YPMATCH 1 +.Os +.Sh NAME +.Nm ypmatch +.Nd "print the values of one or more keys in a YP database" +.Sh SYNOPSIS +.Nm ypmatch +.Op Fl kt +.Op Fl d Ar domainname +.Ar key ... +.Ar mapname +.Nm ypmatch +.Fl x +.Sh DESCRIPTION +.Nm Ypmatch +prints out the values of one or more keys from the +.Tn YP +database specified by +.Ar mapname, +which may be a map name or a map nickname. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar domainname +Specify a domain other than the default domain. +.It Fl k +Display map keys. +This option is useful with maps in which the values are null or the key +is not part of the value. +.It Fl t +Inhibit translation of map nicknames +to their corresponding map names. +.It Fl x +Display the map nickname table. +.El +.Sh SEE ALSO +.Xr ypcat 1 , +.Xr yp 8 +.Sh AUTHOR +Theo De Raadt diff --git a/ypmatch.tproj/ypmatch.c b/ypmatch.tproj/ypmatch.c new file mode 100644 index 0000000..5f78260 --- /dev/null +++ b/ypmatch.tproj/ypmatch.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$Id: ypmatch.c,v 1.1.1.1 1999/05/02 03:59:02 wsanchez Exp $"; +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +struct ypalias { + char *alias, *name; +} ypaliases[] = { + { "passwd", "passwd.byname" }, + { "group", "group.byname" }, + { "networks", "networks.byaddr" }, + { "hosts", "hosts.byname" }, + { "protocols", "protocols.bynumber" }, + { "services", "services.byname" }, + { "aliases", "mail.aliases" }, + { "ethers", "ethers.byname" }, +}; + +usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\typmatch [-d domain] [-t] [-k] key [key ...] mname\n"); + fprintf(stderr, "\typmatch -x\n"); + fprintf(stderr, "where\n"); + fprintf(stderr, "\tmname may be either a mapname or a nickname for a map\n"); + fprintf(stderr, "\t-t inhibits map nickname translation\n"); + fprintf(stderr, "\t-k prints keys as well as values.\n"); + fprintf(stderr, "\t-x dumps the map nickname translation table.\n"); + exit(1); +} + +int +main(argc, argv) +char **argv; +{ + char *domainname; + char *inkey, *inmap, *outbuf; + extern char *optarg; + extern int optind; + int outbuflen, key, notrans; + int c, r, i; + + notrans = key = 0; + yp_get_default_domain(&domainname); + + while( (c=getopt(argc, argv, "xd:kt")) != -1) + switch(c) { + case 'x': + for(i=0; i diff --git a/yppoll.tproj/Makefile.preamble b/yppoll.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/yppoll.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/yppoll.tproj/PB.project b/yppoll.tproj/PB.project new file mode 100644 index 0000000..d763e38 --- /dev/null +++ b/yppoll.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (yppoll.c); + OTHER_SOURCES = (Makefile.dist, Makefile.preamble, yppoll.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = yppoll; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/yppoll.tproj/yppoll.8 b/yppoll.tproj/yppoll.8 new file mode 100644 index 0000000..db17f7b --- /dev/null +++ b/yppoll.tproj/yppoll.8 @@ -0,0 +1,63 @@ +.\" Copyright (c) 1994 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote +.\" products derived from this software without specific prior written +.\" permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: yppoll.8,v 1.1.1.1 1999/05/02 03:59:03 wsanchez Exp $ +.\" +.Dd August 18, 1994 +.Dt YPPOLL 8 +.Os NetBSD +.Sh NAME +.Nm yppoll +.Nd get version of a YP map from YP server +.Sh SYNOPSIS +.Nm yppoll +.Op Fl h Ar host +.Op Fl d Ar domainname +.Ar mapname +.Sh DESCRIPTION +.Nm yppoll +is used to get information of a maps order number and master server. +This utility is useful when determining if different servers have the +same version of a map. +.Nm yppoll +normally talks with the default +.Xr ypserv 8 +process, but by using the +.Fl h +option it is possible to talk with a specific server. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar domain +Don't use default domain, use the specified domain. +.It Fl h Ar host +Get map information from host instead of the default YP server. +.El +.Sh SEE ALSO +.Xr ypserv 8 +.Sh AUTHOR +Theo de Raadt, John Brezak and Mats O Jansson diff --git a/yppoll.tproj/yppoll.c b/yppoll.tproj/yppoll.c new file mode 100644 index 0000000..5f1ddc5 --- /dev/null +++ b/yppoll.tproj/yppoll.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * Copyright (c) 1992, 1993 John Brezak + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt and + * John Brezak. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$Id: yppoll.c,v 1.1.1.1 1999/05/02 03:59:03 wsanchez Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +void +usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\typpoll [-h host] [-d domainname] mapname\n"); + exit(1); +} + +int +get_remote_info(indomain, inmap, server, outorder, outname) + char *indomain; + char *inmap; + char *server; + int *outorder; + char **outname; +{ + struct ypresp_order ypro; + struct ypresp_master yprm; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + struct sockaddr_in rsrv_sin; + int rsrv_sock; + CLIENT *client; + struct hostent *h; + + bzero((char *)&rsrv_sin, sizeof rsrv_sin); + rsrv_sin.sin_len = sizeof rsrv_sin; + rsrv_sin.sin_family = AF_INET; + rsrv_sock = RPC_ANYSOCK; + + h = gethostbyname(server); + if (h == NULL) { + if (inet_aton(server, &rsrv_sin.sin_addr) == 0) { + fprintf(stderr, "unknown host %s\n", server); + exit(1); + } + } else { + rsrv_sin.sin_addr.s_addr = *(u_long *)h->h_addr; + } + + tv.tv_sec = 10; + tv.tv_usec = 0; + + client = clntudp_create(&rsrv_sin, YPPROG, YPVERS, tv, &rsrv_sock); + if (client == NULL) { + fprintf(stderr, "clntudp_create: no contact with host %s.\n", + server); + exit(1); + } + + yprnk.domain = indomain; + yprnk.map = inmap; + + bzero((char *)(char *)&ypro, sizeof ypro); + + r = clnt_call(client, YPPROC_ORDER, xdr_ypreq_nokey, &yprnk, + xdr_ypresp_order, &ypro, tv); + if (r != RPC_SUCCESS) + clnt_perror(client, "yp_order: clnt_call"); + + *outorder = ypro.ordernum; + xdr_free(xdr_ypresp_order, (char *)&ypro); + + r = ypprot_err(ypro.status); + if (r == RPC_SUCCESS) { + bzero((char *)&yprm, sizeof yprm); + + r = clnt_call(client, YPPROC_MASTER, xdr_ypreq_nokey, + &yprnk, xdr_ypresp_master, &yprm, tv); + if (r != RPC_SUCCESS) + clnt_perror(client, "yp_master: clnt_call"); + r = ypprot_err(yprm.status); + if (r==0) + *outname = (char *)strdup(yprm.master); + xdr_free(xdr_ypresp_master, (char *)&yprm); + } + clnt_destroy(client); + return r; +} + +int +main(argc, argv) + int argc; + char **argv; +{ + char *domainname; + char *hostname = NULL; + char *inmap, *master; + int order; + extern char *optarg; + extern int optind; + int c, r; + + yp_get_default_domain(&domainname); + + while ((c=getopt(argc, argv, "h:d:?")) != -1) + switch (c) { + case 'd': + domainname = optarg; + break; + case 'h': + hostname = optarg; + break; + default: + usage(); + /*NOTREACHED*/ + } + + if (optind + 1 != argc ) + usage(); + inmap = argv[optind]; + + if (hostname != NULL) { + r = get_remote_info(domainname, inmap, hostname, + &order, &master); + } else { + r = yp_order(domainname, inmap, &order); + if (r == 0) + r = yp_master(domainname, inmap, &master); + } + + if (r != 0) { + fprintf(stderr, "No such map %s. Reason: %s\n", + inmap, yperr_string(r)); + exit(1); + } + + printf("Map %s has order number %d. %s", inmap, order, + ctime((time_t *)&order)); + printf("The master server is %s.\n", master); + exit(0); +} diff --git a/yppush.tproj/Makefile b/yppush.tproj/Makefile new file mode 100644 index 0000000..ed8971f --- /dev/null +++ b/yppush.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = yppush + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = yppush.h ypdb.h yplib_host.h ypdef.h + +CFILES = ypdb.c yplib_host.c yppush.c yppush_err.c yppush_proc.c\ + yppush_svc.c yppush_xdr.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble yppush.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/yppush.tproj/Makefile.postamble b/yppush.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/yppush.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/yppush.tproj/Makefile.preamble b/yppush.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/yppush.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/yppush.tproj/PB.project b/yppush.tproj/PB.project new file mode 100644 index 0000000..f91db95 --- /dev/null +++ b/yppush.tproj/PB.project @@ -0,0 +1,35 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (yppush.h, ypdb.h, yplib_host.h, ypdef.h); + OTHER_LIBS = (); + OTHER_LINKED = ( + ypdb.c, + yplib_host.c, + yppush.c, + yppush_err.c, + yppush_proc.c, + yppush_svc.c, + yppush_xdr.c + ); + OTHER_SOURCES = (Makefile.preamble, Makefile, Makefile.postamble, yppush.8); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = yppush; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/yppush.tproj/ypdb.c b/yppush.tproj/ypdb.c new file mode 100644 index 0000000..c9bd178 --- /dev/null +++ b/yppush.tproj/ypdb.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "ypdb.h" + +#ifdef YPDB_PATCH +extern DBM *__hash_open(); +#else +extern DBM *__bt_open(); +#endif + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +#else + BTREEINFO info; + char path[MAXPATHLEN]; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + db = (DBM *)__bt_open(path, flags, mode, &info, 0); + return (db); +#endif +} + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open_suf(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + return ((DBM *)__hash_open(file, flags, mode, &info, 0)); +#else + BTREEINFO info; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + db = (DBM *)__bt_open(file, flags, mode, &info, 0); + return (db); +#endif +} + +extern void +ypdb_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_firstkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_nextkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_setkey(db, key) + DBM *db; + datum key; +{ + int status; + datum retdata; +#ifdef YPDB_PATCH + datum retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + while ((retkey.dptr != NULL) && + ((retkey.dsize != key.dsize) || + (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) { + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + }; + return (retkey); +#else + status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR); + if (status) + key.dptr = NULL; + return (key); +#endif +} + +/* + * Returns: + * 0 on success + * <0 failure + */ + +int +ypdb_delete(db, key) + DBM *db; + datum key; +{ + int status; + + status = (db->del)(db, (DBT *)&key, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if YPDB_INSERT and entry exists + */ + +int +ypdb_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0)); +} + diff --git a/yppush.tproj/ypdb.h b/yppush.tproj/ypdb.h new file mode 100644 index 0000000..9afbad5 --- /dev/null +++ b/yppush.tproj/ypdb.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDB_H_ +#define _YPDB_H_ + +#ifndef _DB_H_ +#include +#endif + +#define YPDB_SUFFIX ".db" + +/* Flags to ypdb_store(). */ +#define YPDB_INSERT 0 +#define YPDB_REPLACE 1 + +#ifndef DATUM +typedef struct { + char *dptr; + int dsize; +} datum; +#define DATUM +#endif + +typedef DB DBM; + +__BEGIN_DECLS +void ypdb_close __P((DBM *)); +datum ypdb_fetch __P((DBM *, datum)); +datum ypdb_firstkey __P((DBM *)); +datum ypdb_nextkey __P((DBM *)); +datum ypdb_setkey __P((DBM *, datum)); +DBM *ypdb_open __P((const char *, int, int)); +DBM *ypdb_open_suf __P((const char *, int, int)); +int ypdb_store __P((DBM *, datum, datum, int)); +__END_DECLS + +#endif /* !_YPDB_H_ */ diff --git a/yppush.tproj/ypdef.h b/yppush.tproj/ypdef.h new file mode 100644 index 0000000..89970d7 --- /dev/null +++ b/yppush.tproj/ypdef.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDEF_H_ +#define _YPDEF_H_ + +#define YP_DB_PATH "/var/yp" +#define YP_LAST_KEY "YP_LAST_MODIFIED" +#define YP_LAST_LEN (sizeof(YP_LAST_KEY)-1) +#define YP_INPUT_KEY "YP_INPUT_FILE" +#define YP_INPUT_LEN (sizeof(YP_INPUT_KEY)-1) +#define YP_OUTPUT_KEY "YP_OUTPUT_FILE" +#define YP_OUTPUT_LEN (sizeof(YP_OUTPUT_KEY)-1) +#define YP_MASTER_KEY "YP_MASTER_NAME" +#define YP_MASTER_LEN (sizeof(YP_MASTER_KEY)-1) +#define YP_DOMAIN_KEY "YP_DOMAIN_NAME" +#define YP_DOMAIN_LEN (sizeof(YP_DOMAIN_KEY)-1) +#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN" +#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1) +#define YP_SECURE_KEY "YP_SECURE" +#define YP_SECURE_LEN (sizeof(YP_SECURE_KEY)-1) + +#define MAX_LAST_LEN 10 +#define MAX_MASTER_LEN 255 +#define YP_HOSTNAME "hosts.byname" +#define YP_HOSTADDR "hosts.byaddr" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define YPXFR_PROC "/usr/sbin/ypxfr" +#define YPPUSH_PROC "/usr/sbin/yppush" +#define YPSERV_PID_PATH "/var/run/ypserv.pid" +#define YP_SECURENET_FILE "/var/yp/securenet" + +#endif /* !_YPDEF_H_ */ diff --git a/yppush.tproj/yplib_host.c b/yppush.tproj/yplib_host.c new file mode 100644 index 0000000..70b914b --- /dev/null +++ b/yppush.tproj/yplib_host.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $ */ + +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char *rcsid = "$OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern bool_t xdr_domainname(), xdr_ypbind_resp(); +extern bool_t xdr_ypreq_key(), xdr_ypresp_val(); +extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val(); +extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq(); +extern bool_t xdr_ypresp_master(); + +extern int (*ypresp_allfn)(); +extern void *ypresp_data; + +int _yplib_host_timeout = 10; + +CLIENT * +yp_bind_host(server,program,version,port,usetcp) +char *server; +u_long program,version; +u_short port; +int usetcp; +{ + struct sockaddr_in rsrv_sin; + int rsrv_sock; + struct hostent *h; + struct timeval tv; + static CLIENT *client; + + memset(&rsrv_sin, 0, sizeof rsrv_sin); + rsrv_sin.sin_len = sizeof rsrv_sin; + rsrv_sin.sin_family = AF_INET; + rsrv_sock = RPC_ANYSOCK; + if (port != 0) { + rsrv_sin.sin_port = htons(port); + } + + if ((*server >= '0') && (*server <= '9')) { + if(inet_aton(server,&rsrv_sin.sin_addr) == 0) { + fprintf(stderr, "inet_aton: invalid address %s.\n", + server); + exit(1); + } + } else { + h = gethostbyname(server); + if(h == NULL) { + fprintf(stderr, "gethostbyname: unknown host %s.\n", + server); + exit(1); + } + rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr; + } + + tv.tv_sec = 10; + tv.tv_usec = 0; + + if (usetcp) { + client = clnttcp_create(&rsrv_sin, program, version, + &rsrv_sock, 0, 0); + } else { + client = clntudp_create(&rsrv_sin, program, version, tv, + &rsrv_sock); + } + + if (client == NULL) { + fprintf(stderr, "clntudp_create: no contact with host %s.\n", + server); + exit(1); + } + + return(client); + +} + +CLIENT * +yp_bind_local(program,version) +u_long program,version; +{ + struct sockaddr_in rsrv_sin; + int rsrv_sock; + struct timeval tv; + static CLIENT *client; + + memset(&rsrv_sin, 0, sizeof rsrv_sin); + rsrv_sin.sin_len = sizeof rsrv_sin; + rsrv_sin.sin_family = AF_INET; + rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + rsrv_sock = RPC_ANYSOCK; + + tv.tv_sec = 10; + tv.tv_usec = 0; + + client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock); + if (client == NULL) { + fprintf(stderr,"clntudp_create: no contact with localhost.\n"); + exit(1); + } + + return(client); + +} + +int +yp_match_host(client, indomain, inmap, inkey, inkeylen, outval, outvallen) +CLIENT *client; +char *indomain; +char *inmap; +const char *inkey; +int inkeylen; +char **outval; +int *outvallen; +{ + struct ypresp_val yprv; + struct timeval tv; + struct ypreq_key yprk; + int r; + + *outval = NULL; + *outvallen = 0; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprk.domain = indomain; + yprk.map = inmap; + yprk.key.keydat_val = (char *)inkey; + yprk.key.keydat_len = inkeylen; + + memset(&yprv, 0, sizeof yprv); + + r = clnt_call(client, YPPROC_MATCH, + xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_match_host: clnt_call"); + } + if( !(r=ypprot_err(yprv.stat)) ) { + *outvallen = yprv.val.valdat_len; + *outval = (char *)malloc(*outvallen+1); + memcpy(*outval, yprv.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + } + xdr_free(xdr_ypresp_val, (char *)&yprv); + return r; +} + +int +yp_first_host(client, indomain, inmap, outkey, outkeylen, outval, outvallen) +CLIENT *client; +char *indomain; +char *inmap; +char **outkey; +int *outkeylen; +char **outval; +int *outvallen; +{ + struct ypresp_key_val yprkv; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + + *outkey = *outval = NULL; + *outkeylen = *outvallen = 0; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + memset(&yprkv, 0, sizeof yprkv); + + r = clnt_call(client, YPPROC_FIRST, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_first_host: clnt_call"); + } + if( !(r=ypprot_err(yprkv.stat)) ) { + *outkeylen = yprkv.key.keydat_len; + *outkey = (char *)malloc(*outkeylen+1); + memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); + (*outkey)[*outkeylen] = '\0'; + *outvallen = yprkv.val.valdat_len; + *outval = (char *)malloc(*outvallen+1); + memcpy(*outval, yprkv.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + } + xdr_free(xdr_ypresp_key_val, (char *)&yprkv); + return r; +} + +int +yp_next_host(client, indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen) +CLIENT *client; +char *indomain; +char *inmap; +char *inkey; +int inkeylen; +char **outkey; +int *outkeylen; +char **outval; +int *outvallen; +{ + struct ypresp_key_val yprkv; + struct ypreq_key yprk; + struct timeval tv; + int r; + + *outkey = *outval = NULL; + *outkeylen = *outvallen = 0; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprk.domain = indomain; + yprk.map = inmap; + yprk.key.keydat_val = inkey; + yprk.key.keydat_len = inkeylen; + memset(&yprkv, 0, sizeof yprkv); + + r = clnt_call(client, YPPROC_NEXT, + xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_next_host: clnt_call"); + } + if( !(r=ypprot_err(yprkv.stat)) ) { + *outkeylen = yprkv.key.keydat_len; + *outkey = (char *)malloc(*outkeylen+1); + memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); + (*outkey)[*outkeylen] = '\0'; + *outvallen = yprkv.val.valdat_len; + *outval = (char *)malloc(*outvallen+1); + memcpy(*outval, yprkv.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + } + xdr_free(xdr_ypresp_key_val, (char *)&yprkv); + return r; +} + +int +yp_all_host(client, indomain, inmap, incallback) +CLIENT *client; +char *indomain; +char *inmap; +struct ypall_callback *incallback; +{ + struct ypreq_nokey yprnk; + struct timeval tv; + u_long status; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + ypresp_allfn = incallback->foreach; + ypresp_data = (void *)incallback->data; + + (void) clnt_call(client, YPPROC_ALL, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv); + xdr_free(xdr_ypresp_all_seq, (char *)&status); /* not really needed... */ + + if(status != YP_FALSE) + return ypprot_err(status); + return 0; +} + +int +yp_order_host(client, indomain, inmap, outorder) +CLIENT *client; +char *indomain; +char *inmap; +u_int32_t *outorder; +{ + struct ypresp_order ypro; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + + memset(&ypro, 0, sizeof ypro); + + r = clnt_call(client, YPPROC_ORDER, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_order_host: clnt_call"); + } + + *outorder = ypro.ordernum; + xdr_free(xdr_ypresp_order, (char *)&ypro); + return ypprot_err(ypro.stat); +} + +int +yp_master_host(client, indomain, inmap, outname) +CLIENT *client; +char *indomain; +char *inmap; +char **outname; +{ + struct ypresp_master yprm; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + + memset(&yprm, 0, sizeof yprm); + + r = clnt_call(client, YPPROC_MASTER, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_master: clnt_call"); + } + if( !(r=ypprot_err(yprm.stat)) ) { + *outname = (char *)strdup(yprm.peer); + } + xdr_free(xdr_ypresp_master, (char *)&yprm); + return r; +} + +int +yp_maplist_host(client, indomain, outmaplist) +CLIENT *client; +char *indomain; +struct ypmaplist **outmaplist; +{ + struct ypresp_maplist ypml; + struct timeval tv; + int r; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + memset(&ypml, 0, sizeof ypml); + + r = clnt_call(client, YPPROC_MAPLIST, + xdr_domainname, &indomain, xdr_ypresp_maplist, &ypml, tv); + if (r != RPC_SUCCESS) { + clnt_perror(client, "yp_maplist: clnt_call"); + } + *outmaplist = ypml.maps; + /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/ + return ypprot_err(ypml.stat); +} + diff --git a/yppush.tproj/yplib_host.h b/yppush.tproj/yplib_host.h new file mode 100644 index 0000000..038fb68 --- /dev/null +++ b/yppush.tproj/yplib_host.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplib_host.h,v 1.4 1997/05/01 22:14:45 niklas Exp $ */ + +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPLIB_HOST_H_ +#define _YPLIB_HOST_H_ + +int yp_match_host __P((CLIENT *client, char *indomain, char *inmap, + const char *inkey, int inkeylen, char **outval, + int *outvallen)); +int yp_first_host __P((CLIENT *client, char *indomain, char *inmap, + char **outkey, int *outkeylen, char **outval, + int *outvallen)); +int yp_next_host __P((CLIENT *client, char *indomain, char *inmap, + char *inkey, int inkeylen, char **outkey, + int *outkeylen, char **outval, int *outvallen)); +int yp_master_host __P((CLIENT *client, + char *indomain, char *inmap, char **outname)); +int yp_order_host __P((CLIENT *client, + char *indomain, char *inmap, u_int32_t *outorder)); +int yp_all_host __P((CLIENT *client, char *indomain, char *inmap, + struct ypall_callback *incallback)); +int yp_maplist_host __P((CLIENT *client, char *indomain, + struct ypmaplist **outmaplist)); +CLIENT *yp_bind_local __P((u_long program, u_long version)); +CLIENT *yp_bind_host __P((char *server, u_long program, u_long version, + u_short port, int usetcp)); + +#endif /* _YPLIB_HOST_H_ */ + diff --git a/yppush.tproj/yppush.8 b/yppush.tproj/yppush.8 new file mode 100644 index 0000000..2777199 --- /dev/null +++ b/yppush.tproj/yppush.8 @@ -0,0 +1,68 @@ +.\" $OpenBSD: yppush.8,v 1.4 1997/05/01 21:08:49 niklas Exp $ +.\" Copyright (c) 1995 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd January 29, 1995 +.Dt YPPUSH 8 +.Os +.Sh NAME +.Nm yppush +.Nd force distribution of YP map +.Sh SYNOPSIS +.Nm yppush +.Op Fl d Ar domainname +.Op Fl h Ar hostname +.\" .Op Fl p Ar paralleljobs +.\" .Op Fl t Ar timeout +.Op Fl v +.Ar mapname +.Sh DESCRIPTION +.Nm yppush +is used to distribute an YP map from a master server to any +slave server in the domain. All servers of the domain is fetched from the YP +map ypservers. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar domainname +Don't use default domain, use the specified domain. +.It Fl h Ar hostname +Distribute map only to one host and not to the hosts in the ypserver map. +.\" .It Fl p Ar paralleljobs +.\"Set the number of parallel transfers. +.\".It Fl t Ar timeout +.\"Set the amount of time to elapse before a timeout is registered. +.It Fl v +Verbose. Announce what the program is doing. +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr ypserv 8 +.Sh AUTHOR +Mats O Jansson diff --git a/yppush.tproj/yppush.c b/yppush.tproj/yppush.c new file mode 100644 index 0000000..5ddd82c --- /dev/null +++ b/yppush.tproj/yppush.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppush.c,v 1.10 1997/11/10 05:49:17 deraadt Exp $ */ + +/* + * Copyright (c) 1995 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: yppush.c,v 1.10 1997/11/10 05:49:17 deraadt Exp $"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "yplib_host.h" +#include "ypdef.h" +#include "ypdb.h" + +int Verbose = 0; +char Domain[MAXHOSTNAMELEN], Map[255]; +u_int32_t OrderNum; +char *master; + +extern void yppush_xfrrespprog_1(struct svc_req *request, SVCXPRT *xprt); +extern bool_t xdr_ypreq_xfr(XDR *, struct ypreq_xfr *); + +void +usage() +{ + fprintf(stderr, "Usage:\n"); +/* + fprintf(stderr, "\typpush [-d domainname] [-t seconds] [-p #paralleljobs] [-h host] [-v] mapname\n"); +*/ + fprintf(stderr, "\typpush [-d domainname] [-h host] [-v] mapname\n"); + exit(1); +} + +void +_svc_run() +{ + fd_set readfds; + struct timeval timeout; + + timeout.tv_sec=60; timeout.tv_usec=0; + + for(;;) { + readfds = svc_fdset; + switch (select(_rpc_dtablesize(), &readfds, (void *) 0, + (void *) 0, &timeout)) { + case -1: + if (errno == EINTR) { + continue; + } + perror("yppush: _svc_run: select failed"); + return; + case 0: + fprintf(stderr, "yppush: Callback timed out.\n"); + exit(0); + default: + svc_getreqset(&readfds); + } + } + +} + +void +req_xfr(pid, prog, transp, host, client) +pid_t pid; +u_int prog; +SVCXPRT *transp; +char *host; +CLIENT *client; +{ + struct ypreq_xfr request; + struct timeval tv; + + tv.tv_sec=0; tv.tv_usec=0; + + request.map_parms.domain=(char *)&Domain; + request.map_parms.map=(char *)⤅ + request.map_parms.peer=master; + request.map_parms.ordernum=OrderNum; + request.transid=(u_int)pid; + request.prog=prog; + request.port=transp->xp_port; + + if (Verbose) + printf("%d: %s(%u@%s) -> %s@%s\n", + request.transid, + request.map_parms.map, + request.map_parms.ordernum, + host, + request.map_parms.peer, + request.map_parms.domain); + switch (clnt_call(client, YPPROC_XFR, xdr_ypreq_xfr, &request, + xdr_void, NULL, tv)) { + case RPC_SUCCESS: + case RPC_TIMEDOUT: + break; + default: + clnt_perror(client, "yppush: Cannot call YPPROC_XFR"); + kill(pid, SIGTERM); + } +} + +void +push(inlen, indata) +int inlen; +char *indata; +{ + char host[MAXHOSTNAMELEN]; + CLIENT *client; + SVCXPRT *transp; + int sock = RPC_ANYSOCK; + u_int prog; + bool_t sts; + pid_t pid; + int status; + struct rusage res; + + snprintf(host,sizeof host,"%*.*s" ,inlen ,inlen, indata); + + client = clnt_create(host, YPPROG, YPVERS, "tcp"); + if (client == NULL) { + if (Verbose) + fprintf(stderr,"Target Host: %s\n",host); + clnt_pcreateerror("yppush: Cannot create client"); + return; + } + + transp = svcudp_create(sock); + if (transp == NULL) { + fprintf(stderr, "yppush: Cannot create callback transport.\n"); + return; + } + if (transp->xp_port >= IPPORT_RESERVED) { + SVC_DESTROY(transp); + fprintf(stderr, "yppush: Cannot allocate reserved port.\n"); + return; + } + + for (prog=0x40000000; prog<0x5fffffff; prog++) { + if (sts = svc_register(transp, prog, 1, + yppush_xfrrespprog_1, IPPROTO_UDP)) + break; + } + + if (!sts) { + fprintf(stderr, "yppush: Cannot register callback.\n"); + return; + } + + switch(pid=fork()) { + case -1: + fprintf(stderr, "yppush: Cannot fork.\n"); + exit(1); + case 0: + _svc_run(); + exit(0); + default: + close(transp->xp_sock); + transp->xp_sock = -1; + req_xfr(pid, prog, transp, host, client); + wait4(pid, &status, 0, &res); + svc_unregister(prog, 1); + if (client != NULL) + clnt_destroy(client); + /* XXX transp leak? */ + } + +} + +int +pushit(instatus, inkey, inkeylen, inval, invallen, indata) +int instatus; +char *inkey; +int inkeylen; +char *inval; +int invallen; +char *indata; +{ + if(instatus != YP_TRUE) + return instatus; + push(invallen, inval); + return 0; +} + +int +main(argc, argv) +int argc; +char **argv; +{ + struct ypall_callback ypcb; + extern char *optarg; + extern int optind; + char *domain,*map,*hostname,*parallel,*timeout; + int c, r, i; + char *ypmap = "ypservers"; + CLIENT *client; + static char map_path[MAXPATHLEN]; + struct stat finfo; + DBM *yp_databas; + char order_key[YP_LAST_LEN] = YP_LAST_KEY; + datum o; + + yp_get_default_domain(&domain); + hostname = NULL; +/* + while( (c=getopt(argc, argv, "d:h:p:t:v?")) != -1) +*/ + while( (c=getopt(argc, argv, "d:h:v?")) != -1) + switch(c) { + case 'd': + domain = optarg; + break; + case 'h': + hostname = optarg; + break; + case 'p': + parallel = optarg; + break; + case 't': + timeout = optarg; + break; + case 'v': + Verbose = 1; + break; + case '?': + usage(); + /*NOTREACHED*/ + } + + if(optind + 1 != argc ) + usage(); + + map = argv[optind]; + + strncpy(Domain,domain,sizeof(Domain)-1); + Domain[sizeof(Domain)-1] = '\0'; + strncpy(Map,map,sizeof(Map)-1); + Map[sizeof(Map)-1] = '\0'; + + /* Check domain */ + snprintf(map_path,sizeof map_path,"%s/%s",YP_DB_PATH,domain); + if (!((stat(map_path, &finfo) == 0) && + ((finfo.st_mode & S_IFMT) == S_IFDIR))) { + fprintf(stderr,"yppush: Map does not exist.\n"); + exit(1); + } + + + /* Check map */ + snprintf(map_path,sizeof map_path,"%s/%s/%s%s", + YP_DB_PATH,domain,Map,YPDB_SUFFIX); + if (!(stat(map_path, &finfo) == 0)) { + fprintf(stderr,"yppush: Map does not exist.\n"); + exit(1); + } + + snprintf(map_path,sizeof map_path,"%s/%s/%s",YP_DB_PATH,domain,Map); + yp_databas = ypdb_open(map_path,0,O_RDONLY); + OrderNum=0xffffffff; + if (yp_databas == 0) { + fprintf(stderr, "yppush: %s%s: Cannot open database\n", + map_path, YPDB_SUFFIX); + } else { + o.dptr = (char *) &order_key; + o.dsize = YP_LAST_LEN; + o=ypdb_fetch(yp_databas,o); + if (o.dptr == NULL) { + fprintf(stderr, + "yppush: %s: Cannot determine order number\n", + Map); + } else { + OrderNum=0; + for(i=0; i + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPPUSH_H_RPCGEN +#define _YPPUSH_H_RPCGEN + +#include + + +enum yppush_status { + YPPUSH_SUCC = 1, + YPPUSH_AGE = 2, + YPPUSH_NOMAP = -1, + YPPUSH_NODOM = -2, + YPPUSH_RSRC = -3, + YPPUSH_RPC = -4, + YPPUSH_MADDR = -5, + YPPUSH_YPERR = -6, + YPPUSH_BADARGS = -7, + YPPUSH_DBM = -8, + YPPUSH_FILE = -9, + YPPUSH_SKEW = -10, + YPPUSH_CLEAR = -11, + YPPUSH_FORCE = -12, + YPPUSH_XFRERR = -13, + YPPUSH_REFUSED = -14, +}; +typedef enum yppush_status yppush_status; +#ifdef __cplusplus +extern "C" bool_t xdr_yppush_status(XDR *, yppush_status*); +#elif defined(__STDC__) +extern bool_t xdr_yppush_status(XDR *, yppush_status*); +#else /* Old Style C */ +bool_t xdr_yppush_status(); +#endif /* Old Style C */ + + +struct yppushresp_xfr { + u_int transid; + yppush_status status; +}; +typedef struct yppushresp_xfr yppushresp_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*); +#elif defined(__STDC__) +extern bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*); +#else /* Old Style C */ +bool_t xdr_yppushresp_xfr(); +#endif /* Old Style C */ + + +#define YPPUSH_XFRRESPPROG ((u_long)0x40000000) +#define YPPUSH_XFRRESPVERS ((u_long)1) + +#ifdef __cplusplus +#define YPPUSHPROC_NULL ((u_long)0) +extern "C" void * yppushproc_null_1(void *, CLIENT *); +extern "C" void * yppushproc_null_1_svc(void *, struct svc_req *); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern "C" void * yppushproc_xfrresp_1(yppushresp_xfr *, CLIENT *); +extern "C" void * yppushproc_xfrresp_1_svc(yppushresp_xfr *, struct svc_req *); + +#elif defined(__STDC__) +#define YPPUSHPROC_NULL ((u_long)0) +extern void * yppushproc_null_1(void *, CLIENT *); +extern void * yppushproc_null_1_svc(void *, struct svc_req *); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern void * yppushproc_xfrresp_1(yppushresp_xfr *, CLIENT *); +extern void * yppushproc_xfrresp_1_svc(yppushresp_xfr *, struct svc_req *); + +#else /* Old Style C */ +#define YPPUSHPROC_NULL ((u_long)0) +extern void * yppushproc_null_1(); +extern void * yppushproc_null_1_svc(); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern void * yppushproc_xfrresp_1(); +extern void * yppushproc_xfrresp_1_svc(); +#endif /* Old Style C */ + +#endif /* !_YPPUSH_H_RPCGEN */ diff --git a/yppush.tproj/yppush_err.c b/yppush.tproj/yppush_err.c new file mode 100644 index 0000000..31f74e8 --- /dev/null +++ b/yppush.tproj/yppush_err.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppush_err.c,v 1.2 1996/05/30 09:53:20 deraadt Exp $ */ + +/* + * Copyright (c) 1996 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: yppush_err.c,v 1.2 1996/05/30 09:53:20 deraadt Exp $"; +#endif /* not lint */ + +#include +#include + +char * +yppush_err_string(enum yppush_status y) { + switch(y) { + case YPPUSH_SUCC: + return "Success"; + case YPPUSH_AGE: + return "Master's version not newer"; + case YPPUSH_NOMAP: + return "Can't find server for map"; + case YPPUSH_NODOM: + return "Domain not supported"; + case YPPUSH_RSRC: + return "Local resource alloc failure"; + case YPPUSH_RPC: + return "RPC failure talking to server"; + case YPPUSH_MADDR: + return "Can't get master address"; + case YPPUSH_YPERR: + return "YP server/map db error"; + case YPPUSH_BADARGS: + return "Request arguments bad"; + case YPPUSH_DBM: + return "Local dbm operation failed"; + case YPPUSH_FILE: + return "Local file I/O operation failed"; + case YPPUSH_SKEW: + return "Map version skew during transfer"; + case YPPUSH_CLEAR: + return "Can't send \"Clear\" req to local ypserv"; + case YPPUSH_FORCE: + return "No local order number in map use -f flag."; + case YPPUSH_XFRERR: + return "ypxfr error"; + case YPPUSH_REFUSED: + return "Transfer request refused by ypserv"; + } +}; diff --git a/yppush.tproj/yppush_proc.c b/yppush.tproj/yppush_proc.c new file mode 100644 index 0000000..601a7cb --- /dev/null +++ b/yppush.tproj/yppush_proc.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppush_proc.c,v 1.3 1997/08/21 12:52:08 maja Exp $ */ + +/* + * Copyright (c) 1996 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: yppush_proc.c,v 1.3 1997/08/21 12:52:08 maja Exp $"; +#endif /* not lint */ + +#include +#include "yppush.h" + +extern int Verbose; + +void * +yppushproc_null_1_svc(argp, rqstp) + void *argp; + struct svc_req *rqstp; +{ + + static char* result; + + /* + * insert server code here + */ + return((void*) &result); +} + +void * +yppushproc_xfrresp_1_svc(argp, rqstp) + yppushresp_xfr *argp; + struct svc_req *rqstp; +{ + + static char* result; + + /* + * insert server code here + */ + if ((argp->statusstatus)); + + return((void*) &result); +} diff --git a/yppush.tproj/yppush_svc.c b/yppush.tproj/yppush_svc.c new file mode 100644 index 0000000..f3c19dc --- /dev/null +++ b/yppush.tproj/yppush_svc.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppush_svc.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $ */ + +/* + * Copyright (c) 1996 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char rcsid[] = "$OpenBSD: yppush_svc.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $"; +#endif /* not lint */ + +#include "yppush.h" +#include +#include /* getenv, exit */ +#include +#include +#include /* TIOCNOTTY */ +#include +#include +#include +#ifdef SYSLOG +#include +#else +#define LOG_ERR 1 +#define openlog(a, b, c) +#endif + +#ifdef __STDC__ +#define SIG_PF void(*)(int) +#endif + +#ifdef DEBUG +#define RPC_SVC_FG +#endif + +#define _RPCSVC_CLOSEDOWN 120 +int _rpcpmstart; /* Started by a port monitor ? */ +int _rpcfdtype; /* Whether Stream or Datagram ? */ +int _rpcsvcdirty; /* Still serving ? */ + +static +void _msgout(msg) + char *msg; +{ +#ifdef RPC_SVC_FG + if (_rpcpmstart) + syslog(LOG_ERR, msg); + else + (void) fprintf(stderr, "%s\n", msg); +#else + syslog(LOG_ERR, msg); +#endif +} + +void +yppush_xfrrespprog_1(rqstp, transp) + struct svc_req *rqstp; + register SVCXPRT *transp; +{ + union { + int fill; + } argument; + char *result; + bool_t (*xdr_argument)(), (*xdr_result)(); + char *(*local)(); + + _rpcsvcdirty = 1; + switch (rqstp->rq_proc) { + case YPPUSHPROC_NULL: + xdr_argument = xdr_void; + xdr_result = xdr_void; + local = (char *(*)()) yppushproc_null_1_svc; + break; + + case YPPUSHPROC_XFRRESP: + xdr_argument = xdr_yppushresp_xfr; + xdr_result = xdr_void; + local = (char *(*)()) yppushproc_xfrresp_1_svc; + break; + + default: + svcerr_noproc(transp); + _rpcsvcdirty = 0; + exit(1); + return; + } + (void) memset((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) { + svcerr_decode(transp); + _rpcsvcdirty = 0; + exit(1); + return; + } + result = (*local)(&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) { + _msgout("unable to free arguments"); + exit(1); + } + _rpcsvcdirty = 0; + if (rqstp->rq_proc!=YPPUSHPROC_NULL) + exit(0); + return; +} diff --git a/yppush.tproj/yppush_xdr.c b/yppush.tproj/yppush_xdr.c new file mode 100644 index 0000000..d8ad787 --- /dev/null +++ b/yppush.tproj/yppush_xdr.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yppush_xdr.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $ */ + +/* + * Copyright (c) 1996 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: yppush_xdr.c,v 1.2 1996/05/30 09:53:22 deraadt Exp $"; +#endif + +#include +#include + +__private_extern__ +bool_t +xdr_domainname(xdrs, objp) + XDR *xdrs; + domainname *objp; +{ + if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_mapname(xdrs, objp) + XDR *xdrs; + mapname *objp; +{ + if (!xdr_string(xdrs, objp, YPMAXMAP)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_peername(xdrs, objp) + XDR *xdrs; + peername *objp; +{ + if (!xdr_string(xdrs, objp, YPMAXPEER)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypmap_parms(xdrs, objp) + XDR *xdrs; + ypmap_parms *objp; +{ + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ordernum)) { + return (FALSE); + } + if (!xdr_peername(xdrs, &objp->peer)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypreq_xfr(xdrs, objp) + XDR *xdrs; + ypreq_xfr *objp; +{ + if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->prog)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->port)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yppush_status(xdrs, objp) + XDR *xdrs; + yppush_status *objp; +{ + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yppushresp_xfr(xdrs, objp) + XDR *xdrs; + yppushresp_xfr *objp; +{ + + register long *buf; + + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_yppush_status(xdrs, &objp->status)) { + return (FALSE); + } + return (TRUE); +} + + + diff --git a/ypserv.tproj/Makefile b/ypserv.tproj/Makefile new file mode 100644 index 0000000..626fbef --- /dev/null +++ b/ypserv.tproj/Makefile @@ -0,0 +1,52 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypserv + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = acl.h yp.h ypv1.h ypdb.h yplog.h ypdef.h + +CFILES = acl.c ypdb.c yplog.c ypserv.c ypserv_db.c ypserv_proc.c\ + ypserv_xdr.c ypserv_xdr_v1.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble securenet\ + securenet.5 ypserv.acl ypserv.acl.5 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/libexec +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_BUILD_OUTPUT_DIR = /tmp/$(USER)/BUILD + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypserv.tproj/Makefile.postamble b/ypserv.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/ypserv.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/ypserv.tproj/Makefile.preamble b/ypserv.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/ypserv.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/ypserv.tproj/PB.project b/ypserv.tproj/PB.project new file mode 100644 index 0000000..c7cbbbb --- /dev/null +++ b/ypserv.tproj/PB.project @@ -0,0 +1,45 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (acl.h, yp.h, ypv1.h, ypdb.h, yplog.h, ypdef.h); + OTHER_LIBS = (); + OTHER_LINKED = ( + acl.c, + ypdb.c, + yplog.c, + ypserv.c, + ypserv_db.c, + ypserv_proc.c, + ypserv_xdr.c, + ypserv_xdr_v1.c + ); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + securenet, + securenet.5, + ypserv.acl, + ypserv.acl.5 + ); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDDIR = "/tmp/$(USER)/BUILD"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/libexec; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypserv; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypserv.tproj/acl.c b/ypserv.tproj/acl.c new file mode 100644 index 0000000..14e767f --- /dev/null +++ b/ypserv.tproj/acl.c @@ -0,0 +1,641 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: acl.c,v 1.5 1997/08/05 09:26:55 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: acl.c,v 1.5 1997/08/05 09:26:55 maja Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "acl.h" + +#define TRUE 1 +#define FALSE 0 + +static struct aclent *acl_root = NULL; + +static int acl_read_line(fp, buf, size) +FILE *fp; +char *buf; +int size; +{ + int len = 0; + char *c,*p,l; + + /* Read a line, and remove any comment, trim space */ + + do { + while (fgets(buf, size, fp)) { + c = buf; + while(*c != '\0') { + if ((*c == '#') || (*c == '\n')) { + *c = '\0'; + } else { + c++; + } + } + + c = p = buf; l = ' '; + while(*c != '\0') { + if ((isspace(l) != 0) && (isspace(*c) != 0)) { + c++; + } else { + l = *c++; *p = l; p++; + } + } + *p = '\0'; + + if (p != buf) { + --p; + if (isspace(*p) != 0) { + *p = '\0'; + } + } + + len = strlen(buf); + return len + 1; + } + } while (size > 0 && !feof(fp)); + + return len; +} + +int +acl_check_host(addr) +struct in_addr *addr; +{ + struct aclent *p; + + p = acl_root; + while (p != NULL) { + if ((addr->s_addr & p->s_mask) == p->s_addr) { + return(p->allow); + } + p = p->next; + } + return(TRUE); +} + +void +acl_add_net(allow,addr,mask) +int allow; +struct in_addr *addr,*mask; +{ + + struct aclent *acl,*p; + + acl = (struct aclent *) malloc((unsigned) sizeof(struct aclent)); + + acl->next = NULL; + acl->allow = allow; + acl->s_addr = addr->s_addr; + acl->s_mask = mask->s_addr; + + if (acl_root == NULL) { + acl_root = acl; + } else { + p = acl_root; + while (p->next != NULL) + p = p->next; + p->next = acl; + } + +} + +void +acl_add_host(allow,addr) +int allow; +struct in_addr *addr; +{ + struct in_addr mask; + + mask.s_addr = htonl(0xffffffff); + + acl_add_net(allow,addr,&mask); +} + +int +acl_init(file) +char *file; +{ + char data_line[1024]; + int line_no = 0; + int len,i; + int allow = TRUE; + int error_cnt = 0; + char *p,*k; + int state; + struct in_addr addr,mask,*host_addr; + struct hostent *host; + struct netent *net; + FILE *data_file = NULL; + + if (file != NULL) { + data_file = fopen(file,"r"); + }; + + while ((data_file != NULL) && + (acl_read_line(data_file,data_line,sizeof(data_line)))) { + + line_no++; + + len = strlen(data_line); + if (len == 0) { + continue; + } + + p = (char *) &data_line; + + /* State 1: Initial State */ + + state = ACLS_INIT; + addr.s_addr = mask.s_addr = 0; + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + } + + if (strcmp(k,"allow") == 0) { + allow = TRUE; + state = ACLS_ALLOW; + } + + if (strcmp(k,"deny") == 0) { + allow = FALSE; + state = ACLS_DENY; + } + + if (state == ACLS_INIT) { + state = ACLE_UVERB; + } + + /* State 2: allow row */ + /* State 3: deny row */ + + if ((*p != '\0') && + ((state == ACLS_ALLOW) || (state == ACLS_DENY))) { + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + } + + if (strcmp(k,"all") == 0) { + state = state + ACLD_ALL; + } + + if (strcmp(k,"host") == 0) { + state = state + ACLD_HOST; + } + + if (strcmp(k,"net") == 0) { + state = state + ACLD_NET; + } + + if ((state == ACLS_ALLOW) || (state == ACLS_DENY)) { + state = ACLE_U2VERB; + } + + } + + if ((state == ACLS_ALLOW) || (state == ACLS_DENY)) { + state = ACLE_UEOL; + } + + /* State 4 & 5: all state, remove any comment */ + + if ((*p == '\0') && + ((state == ACLS_ALLOW_ALL) || (state == ACLS_DENY_ALL))) { + acl_add_net(allow,&addr,&mask); + state = ACLE_OK; + } + + /* State 6 & 7: host line */ + /* State 8 & 9: net line */ + + if ((*p != '\0') && + (state >= ACLS_ALLOW_HOST) && (state <= ACLS_DENY_NET)) { + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + } + + if ((state == ACLS_ALLOW_HOST) || (state == ACLS_DENY_HOST)) { + if ((*k >= '0') && (*k <= '9')) { + (void)inet_aton(k,&addr); + acl_add_host(allow,&addr); + state = state + ACLD_HOST_DONE; + } else { + host = gethostbyname(k); + if (host == NULL) { + state = ACLE_NOHOST; + } else { + if (host->h_addrtype == AF_INET) { + while ((host_addr = (struct in_addr *) *host->h_addr_list++) + != NULL) + acl_add_host(allow,host_addr); + } + state = state + ACLD_HOST_DONE; + } + } + } + + if ((state == ACLS_ALLOW_NET) || (state == ACLS_DENY_NET)) { + if ((*k >= '0') && (*k <= '9')) { + (void)inet_aton(k,&addr); + state = state + ACLD_NET_DONE; + } else { + net = getnetbyname(k); + if (net == NULL) { + state = ACLE_NONET; + } else { + addr.s_addr = ntohl(net->n_net); + state = state + ACLD_NET_DONE; + } + } + } + + } + + if ((state >= ACLS_ALLOW_HOST) && (state <= ACLS_DENY_NET)) { + state = ACLE_UEOL; + } + + /* State 10 & 11: allow/deny host line */ + + if ((*p == '\0') && + ((state == ACLS_ALLOW_HOST_DONE) || (state == ACLS_DENY_HOST_DONE))) { + state = ACLE_OK; + } + + /* State 12 & 13: allow/deny net line */ + + if ((*p == '\0') && + ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE))) { + mask.s_addr = htonl(0xffffff00); + if (ntohl(addr.s_addr) < 0xc0000000) { + mask.s_addr = htonl(0xffff0000); + } + if (ntohl(addr.s_addr) < 0x80000000) { + mask.s_addr = htonl(0xff000000); + } + acl_add_net(allow,&addr,&mask); + state = ACLE_OK; + } + + if ((*p != '\0') && + ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE))) { + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + } + + if (strcmp(k,"netmask") == 0) { + state = state + ACLD_NET_MASK; + } + + if ((state == ACLS_ALLOW_NET_DONE) || (state == ACLS_DENY_NET_DONE)) { + state = ACLE_NONETMASK; + } + + } + + /* State 14 & 15: allow/deny net netmask line */ + + if ((*p != '\0') && + ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK))) { + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + } + + if ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK)) { + if ((*k >= '0') && (*k <= '9')) { + (void)inet_aton(k,&mask); + state = state + ACLD_NET_EOL; + } else { + net = getnetbyname(k); + if (net == NULL) { + state = ACLE_NONET; + } else { + mask.s_addr = ntohl(net->n_net); + state = state + ACLD_NET_EOL; + } + } + } + + } + + if ((state == ACLS_ALLOW_NET_MASK) || (state == ACLS_DENY_NET_MASK)) { + state = ACLE_UEOL; + } + + /* State 16 & 17: allow/deny host line */ + + if ((*p == '\0') && + ((state == ACLS_ALLOW_NET_EOL) || (state == ACLS_DENY_NET_EOL))) { + acl_add_net(allow,&addr,&mask); + state = ACLE_OK; + } + + switch (state) { + case ACLE_NONETMASK: + fprintf(stderr,"acl: excpected \"netmask\" missing at line %d\n",line_no); + break; + case ACLE_NONET: + error_cnt++; + fprintf(stderr,"acl: unknown network at line %d\n",line_no); + break; + case ACLE_NOHOST: + error_cnt++; + fprintf(stderr,"acl: unknown host at line %d\n",line_no); + break; + case ACLE_UVERB: + error_cnt++; + fprintf(stderr,"acl: unknown verb at line %d\n",line_no); + break; + case ACLE_U2VERB: + error_cnt++; + fprintf(stderr,"acl: unknown secondary verb at line %d\n",line_no); + break; + case ACLE_UEOL: + error_cnt++; + fprintf(stderr,"acl: unexpected end of line at line %d\n",line_no); + break; + case ACLE_OK: + break; + default: + error_cnt++; + fprintf(stderr,"acl: unexpected state %d %s\n",state,k); + } + + } + + if (data_file != NULL) { + (void)fflush(stderr); + (void)fclose(data_file); + } + + /* Always add a last allow all if file don't exists or */ + /* the file doesn't cover all cases. */ + + addr.s_addr = mask.s_addr = 0; + allow = TRUE; + acl_add_net(allow,&addr,&mask); + + return(error_cnt); + +} + +int +acl_securenet(file) +char *file; +{ + char data_line[1024]; + int line_no = 0; + int len,i; + int allow = TRUE; + int error_cnt = 0; + char *p,*k; + int state; + struct in_addr addr,mask; + struct netent *net; + FILE *data_file = NULL; + + if (file != NULL) { + data_file = fopen(file,"r"); + }; + + /* Always add a localhost allow first, to be compatable with sun */ + + addr.s_addr = htonl(0x7f000001); + mask.s_addr = htonl(0xffffffff); + allow = TRUE; + acl_add_net(allow,&addr,&mask); + + while ((data_file != NULL) && + (acl_read_line(data_file,data_line,sizeof(data_line)))) { + + line_no++; + + len = strlen(data_line); + if (len == 0) { + continue; + } + + p = (char *) &data_line; + + /* State 1: Initial State */ + + state = ACLS_INIT; + addr.s_addr = mask.s_addr = 0; + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + state = ACLS_ALLOW_NET_MASK; + } + + if (state == ACLS_INIT) { + state = ACLE_UEOL; + } + + if (state == ACLS_ALLOW_NET_MASK) { + + if ((*k >= '0') && (*k <= '9')) { + (void)inet_aton(k,&mask); + state = ACLS_ALLOW_NET; + } else { + net = getnetbyname(k); + if (net == NULL) { + state = ACLE_NONET; + } else { + mask.s_addr = ntohl(net->n_net); + state = ACLS_ALLOW_NET; + } + } + + k = p; i = 0; /* save start of verb */ + while ((*p != '\0') && + (!isspace(*p = tolower(*p)))) { + p++; i++; + }; + + if (*p != '\0') { + *p++ = '\0'; + } + } + + if ((state == ACLS_ALLOW_NET_MASK)) { + state = ACLE_UEOL; + } + + if (state == ACLS_ALLOW_NET) { + + if ((*k >= '0') && (*k <= '9')) { + (void)inet_aton(k,&addr); + state = ACLS_ALLOW_NET_EOL; + } else { + net = getnetbyname(k); + if (net == NULL) { + state = ACLE_NONET; + } else { + addr.s_addr = ntohl(net->n_net); + state = ACLS_ALLOW_NET_EOL; + } + } + } + + if ((state == ACLS_ALLOW_NET)) { + state = ACLE_UEOL; + } + + if ((*p == '\0') && (state == ACLS_ALLOW_NET_EOL)) { + acl_add_net(allow,&addr,&mask); + state = ACLE_OK; + } + + switch (state) { + case ACLE_NONET: + error_cnt++; + fprintf(stderr,"securenet: unknown network at line %d\n",line_no); + break; + case ACLE_UEOL: + error_cnt++; + fprintf(stderr,"securenet: unexpected end of line at line %d\n",line_no); + break; + case ACLE_OK: + break; + default: + error_cnt++; + fprintf(stderr,"securenet: unexpected state %d %s\n",state,k); + } + + } + + if (data_file != NULL) { + (void)fflush(stderr); + (void)fclose(data_file); + + /* Always add a last deny all if file exists */ + + addr.s_addr = mask.s_addr = 0; + allow = FALSE; + acl_add_net(allow,&addr,&mask); + + } + + /* Always add a last allow all if file don't exists */ + + addr.s_addr = mask.s_addr = 0; + allow = TRUE; + acl_add_net(allow,&addr,&mask); + + return(error_cnt); + +} + +void +acl_reset() +{ + struct aclent *p; + + while (acl_root != NULL) { + p = acl_root->next; + free(acl_root); + acl_root = p; + } +} diff --git a/ypserv.tproj/acl.h b/ypserv.tproj/acl.h new file mode 100644 index 0000000..cb10663 --- /dev/null +++ b/ypserv.tproj/acl.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: acl.h,v 1.4 1996/06/30 19:46:05 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _ACL_H_ +#define _ACL_H_ + +#define ACLD_ALL 2 +#define ACLD_HOST 4 +#define ACLD_NET 6 +#define ACLD_HOST_DONE 4 +#define ACLD_NET_DONE 4 +#define ACLD_NET_MASK 2 +#define ACLD_NET_EOL 2 + +#define ACLS_INIT 1 +#define ACLS_ALLOW 2 +#define ACLS_DENY 3 +#define ACLS_ALLOW_ALL ACLS_ALLOW+ACLD_ALL /* 4 */ +#define ACLS_DENY_ALL ACLS_DENY+ACLD_ALL /* 5 */ +#define ACLS_ALLOW_HOST ACLS_ALLOW+ACLD_HOST /* 6 */ +#define ACLS_DENY_HOST ACLS_DENY+ACLD_HOST /* 7 */ +#define ACLS_ALLOW_NET ACLS_ALLOW+ACLD_NET /* 8 */ +#define ACLS_DENY_NET ACLS_DENY+ACLD_NET /* 9 */ +#define ACLS_ALLOW_HOST_DONE ACLS_ALLOW_HOST+ACLD_HOST_DONE /* 10 */ +#define ACLS_DENY_HOST_DONE ACLS_DENY_HOST+ACLD_HOST_DONE /* 11 */ +#define ACLS_ALLOW_NET_DONE ACLS_ALLOW_NET+ACLD_NET_DONE /* 12 */ +#define ACLS_DENY_NET_DONE ACLS_DENY_NET+ACLD_NET_DONE /* 13 */ +#define ACLS_ALLOW_NET_MASK ACLS_ALLOW_NET_DONE+ACLD_NET_MASK /* 14 */ +#define ACLS_DENY_NET_MASK ACLS_DENY_NET_DONE+ACLD_NET_MASK /* 15 */ +#define ACLS_ALLOW_NET_EOL ACLS_ALLOW_NET_MASK+ACLD_NET_EOL /* 16 */ +#define ACLS_DENY_NET_EOL ACLS_DENY_NET_MASK+ACLD_NET_EOL /* 17 */ + +#define ACLE_NONETMASK 18 +#define ACLE_NONET 19 +#define ACLE_NOHOST 20 +#define ACLE_UVERB 21 +#define ACLE_U2VERB 22 +#define ACLE_UEOL 23 +#define ACLE_OK 24 + +struct aclent { +struct aclent *next; + int allow; + u_long s_addr; + u_long s_mask; +}; + +__BEGIN_DECLS +int acl_check_host __P((struct in_addr *)); +int acl_init __P((char *)); +int acl_securenet __P((char *)); +void acl_reset __P((void)); +__END_DECLS + +#endif /* !_ACL_H_ */ + + diff --git a/ypserv.tproj/securenet b/ypserv.tproj/securenet new file mode 100644 index 0000000..a136cfb --- /dev/null +++ b/ypserv.tproj/securenet @@ -0,0 +1,4 @@ +# +# Only my local net is secure. +# +255.255.255.0 139.58.253.0 diff --git a/ypserv.tproj/securenet.5 b/ypserv.tproj/securenet.5 new file mode 100644 index 0000000..bb14ae7 --- /dev/null +++ b/ypserv.tproj/securenet.5 @@ -0,0 +1,74 @@ +.\" $OpenBSD: securenet.5,v 1.4 1996/06/26 21:26:37 maja Exp $ +.\" Copyright (c) 1994 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd June 27, 1994 +.Dt SECURENET 5 +.Os +.Sh NAME +.Nm securenet +.Nd +.Xr ypserv 8 +configuration file for secure networks +.Sh DESCRIPTION +The +.Nm securenet +file controls which hosts can connect to the +.Nm YP +server. +.Pp +The format is rather simple. Each row consists of two items. The first item +is the network mask. The second item is the network. +.Sh EXAMPLES +.Pp +A configuration file might appear as follows: +.Bd -literal +# +# Only my local net is secure. +# +255.255.255.0 139.58.253.0 +.Ed +.Sh FILES +.Bl -tag -width /var/yp/securenet -compact +.It Pa /var/yp/securenet +A +.Xr ypserv 8 +configuration file. +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr ypserv 8 , +.Xr ypserv.acl 5 +.Sh HISTORY +The +.Nm securenet +was added to +.Nm NIS +by Sun Microsystems, Inc. as a bugfix for weak security. + diff --git a/ypserv.tproj/yp.h b/ypserv.tproj/yp.h new file mode 100644 index 0000000..cfe590b --- /dev/null +++ b/ypserv.tproj/yp.h @@ -0,0 +1,612 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yp.h,v 1.5 1997/07/25 20:12:31 mickey Exp $ */ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _YP_H_RPCGEN +#define _YP_H_RPCGEN + +#include + +#define YPMAXRECORD 1024 +#define YPMAXDOMAIN 64 +#define YPMAXMAP 64 +#define YPMAXPEER 64 + +enum ypstat { + YP_TRUE = 1, + YP_NOMORE = 2, + YP_FALSE = 0, + YP_NOMAP = -1, + YP_NODOM = -2, + YP_NOKEY = -3, + YP_BADOP = -4, + YP_BADDB = -5, + YP_YPERR = -6, + YP_BADARGS = -7, + YP_VERS = -8, +}; +typedef enum ypstat ypstat; +#ifdef __cplusplus +extern "C" bool_t xdr_ypstat(XDR *, ypstat*); +#elif defined(__STDC__) +extern bool_t xdr_ypstat(XDR *, ypstat*); +#else /* Old Style C */ +bool_t xdr_ypstat(); +#endif /* Old Style C */ + + +enum ypxfrstat { + YPXFR_SUCC = 1, + YPXFR_AGE = 2, + YPXFR_NOMAP = -1, + YPXFR_NODOM = -2, + YPXFR_RSRC = -3, + YPXFR_RPC = -4, + YPXFR_MADDR = -5, + YPXFR_YPERR = -6, + YPXFR_BADARGS = -7, + YPXFR_DBM = -8, + YPXFR_FILE = -9, + YPXFR_SKEW = -10, + YPXFR_CLEAR = -11, + YPXFR_FORCE = -12, + YPXFR_XFRERR = -13, + YPXFR_REFUSED = -14, +}; +typedef enum ypxfrstat ypxfrstat; +#ifdef __cplusplus +extern "C" bool_t xdr_ypxfrstat(XDR *, ypxfrstat*); +#elif defined(__STDC__) +extern bool_t xdr_ypxfrstat(XDR *, ypxfrstat*); +#else /* Old Style C */ +bool_t xdr_ypxfrstat(); +#endif /* Old Style C */ + + +typedef char *domainname; +#ifdef __cplusplus +extern "C" bool_t xdr_domainname(XDR *, domainname*); +#elif defined(__STDC__) +extern bool_t xdr_domainname(XDR *, domainname*); +#else /* Old Style C */ +bool_t xdr_domainname(); +#endif /* Old Style C */ + + +typedef char *mapname; +#ifdef __cplusplus +extern "C" bool_t xdr_mapname(XDR *, mapname*); +#elif defined(__STDC__) +extern bool_t xdr_mapname(XDR *, mapname*); +#else /* Old Style C */ +bool_t xdr_mapname(); +#endif /* Old Style C */ + + +typedef char *peername; +#ifdef __cplusplus +extern "C" bool_t xdr_peername(XDR *, peername*); +#elif defined(__STDC__) +extern bool_t xdr_peername(XDR *, peername*); +#else /* Old Style C */ +bool_t xdr_peername(); +#endif /* Old Style C */ + + +typedef struct { + u_int keydat_len; + char *keydat_val; +} keydat; +#ifdef __cplusplus +extern "C" bool_t xdr_keydat(XDR *, keydat*); +#elif defined(__STDC__) +extern bool_t xdr_keydat(XDR *, keydat*); +#else /* Old Style C */ +bool_t xdr_keydat(); +#endif /* Old Style C */ + + +typedef struct { + u_int valdat_len; + char *valdat_val; +} valdat; +#ifdef __cplusplus +extern "C" bool_t xdr_valdat(XDR *, valdat*); +#elif defined(__STDC__) +extern bool_t xdr_valdat(XDR *, valdat*); +#else /* Old Style C */ +bool_t xdr_valdat(); +#endif /* Old Style C */ + + +struct ypmap_parms { + domainname domain; + mapname map; + u_int32_t ordernum; + peername peer; +}; +typedef struct ypmap_parms ypmap_parms; +#ifdef __cplusplus +extern "C" bool_t xdr_ypmap_parms(XDR *, ypmap_parms*); +#elif defined(__STDC__) +extern bool_t xdr_ypmap_parms(XDR *, ypmap_parms*); +#else /* Old Style C */ +bool_t xdr_ypmap_parms(); +#endif /* Old Style C */ + + +struct ypreq_key { + domainname domain; + mapname map; + keydat key; +}; +typedef struct ypreq_key ypreq_key; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreq_key(XDR *, ypreq_key*); +#elif defined(__STDC__) +extern bool_t xdr_ypreq_key(XDR *, ypreq_key*); +#else /* Old Style C */ +bool_t xdr_ypreq_key(); +#endif /* Old Style C */ + + +struct ypreq_nokey { + domainname domain; + mapname map; +}; +typedef struct ypreq_nokey ypreq_nokey; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreq_nokey(XDR *, ypreq_nokey*); +#elif defined(__STDC__) +extern bool_t xdr_ypreq_nokey(XDR *, ypreq_nokey*); +#else /* Old Style C */ +bool_t xdr_ypreq_nokey(); +#endif /* Old Style C */ + + +struct ypreq_xfr { + ypmap_parms map_parms; + u_int transid; + u_int prog; + u_int port; +}; +typedef struct ypreq_xfr ypreq_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreq_xfr(XDR *, ypreq_xfr*); +#elif defined(__STDC__) +extern bool_t xdr_ypreq_xfr(XDR *, ypreq_xfr*); +#else /* Old Style C */ +bool_t xdr_ypreq_xfr(); +#endif /* Old Style C */ + + +struct ypresp_val { + ypstat stat; + valdat val; +}; +typedef struct ypresp_val ypresp_val; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_val(XDR *, ypresp_val*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_val(XDR *, ypresp_val*); +#else /* Old Style C */ +bool_t xdr_ypresp_val(); +#endif /* Old Style C */ + + +struct ypresp_key_val { + ypstat stat; + keydat key; + valdat val; +}; +typedef struct ypresp_key_val ypresp_key_val; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_key_val(XDR *, ypresp_key_val*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_key_val(XDR *, ypresp_key_val*); +#else /* Old Style C */ +bool_t xdr_ypresp_key_val(); +#endif /* Old Style C */ + + +struct ypresp_master { + ypstat stat; + peername peer; +}; +typedef struct ypresp_master ypresp_master; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_master(XDR *, ypresp_master*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_master(XDR *, ypresp_master*); +#else /* Old Style C */ +bool_t xdr_ypresp_master(); +#endif /* Old Style C */ + + +struct ypresp_order { + ypstat stat; + u_int32_t ordernum; +}; +typedef struct ypresp_order ypresp_order; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_order(XDR *, ypresp_order*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_order(XDR *, ypresp_order*); +#else /* Old Style C */ +bool_t xdr_ypresp_order(); +#endif /* Old Style C */ + + +struct ypresp_all { + bool_t more; + union { + ypresp_key_val val; + } ypresp_all_u; +}; +typedef struct ypresp_all ypresp_all; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_all(XDR *, ypresp_all*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_all(XDR *, ypresp_all*); +#else /* Old Style C */ +bool_t xdr_ypresp_all(); +#endif /* Old Style C */ + + +struct ypresp_xfr { + u_int transid; + ypxfrstat xfrstat; +}; +typedef struct ypresp_xfr ypresp_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_xfr(XDR *, ypresp_xfr*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_xfr(XDR *, ypresp_xfr*); +#else /* Old Style C */ +bool_t xdr_ypresp_xfr(); +#endif /* Old Style C */ + + +struct ypmaplist { + mapname map; + struct ypmaplist *next; +}; +typedef struct ypmaplist ypmaplist; +#ifdef __cplusplus +extern "C" bool_t xdr_ypmaplist(XDR *, ypmaplist*); +#elif defined(__STDC__) +extern bool_t xdr_ypmaplist(XDR *, ypmaplist*); +#else /* Old Style C */ +bool_t xdr_ypmaplist(); +#endif /* Old Style C */ + + +struct ypresp_maplist { + ypstat stat; + ypmaplist *maps; +}; +typedef struct ypresp_maplist ypresp_maplist; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_maplist(XDR *, ypresp_maplist*); +#elif defined(__STDC__) +extern bool_t xdr_ypresp_maplist(XDR *, ypresp_maplist*); +#else /* Old Style C */ +bool_t xdr_ypresp_maplist(); +#endif /* Old Style C */ + + +enum yppush_status { + YPPUSH_SUCC = 1, + YPPUSH_AGE = 2, + YPPUSH_NOMAP = -1, + YPPUSH_NODOM = -2, + YPPUSH_RSRC = -3, + YPPUSH_RPC = -4, + YPPUSH_MADDR = -5, + YPPUSH_YPERR = -6, + YPPUSH_BADARGS = -7, + YPPUSH_DBM = -8, + YPPUSH_FILE = -9, + YPPUSH_SKEW = -10, + YPPUSH_CLEAR = -11, + YPPUSH_FORCE = -12, + YPPUSH_XFRERR = -13, + YPPUSH_REFUSED = -14, +}; +typedef enum yppush_status yppush_status; +#ifdef __cplusplus +extern "C" bool_t xdr_yppush_status(XDR *, yppush_status*); +#elif defined(__STDC__) +extern bool_t xdr_yppush_status(XDR *, yppush_status*); +#else /* Old Style C */ +bool_t xdr_yppush_status(); +#endif /* Old Style C */ + + +struct yppushresp_xfr { + u_int transid; + yppush_status status; +}; +typedef struct yppushresp_xfr yppushresp_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*); +#elif defined(__STDC__) +extern bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*); +#else /* Old Style C */ +bool_t xdr_yppushresp_xfr(); +#endif /* Old Style C */ + + +enum ypbind_resptype { + YPBIND_SUCC_VAL = 1, + YPBIND_FAIL_VAL = 2, +}; +typedef enum ypbind_resptype ypbind_resptype; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_resptype(XDR *, ypbind_resptype*); +#elif defined(__STDC__) +extern bool_t xdr_ypbind_resptype(XDR *, ypbind_resptype*); +#else /* Old Style C */ +bool_t xdr_ypbind_resptype(); +#endif /* Old Style C */ + + +struct ypbind_binding { + char ypbind_binding_addr[4]; + char ypbind_binding_port[2]; +}; +typedef struct ypbind_binding ypbind_binding; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_binding(XDR *, ypbind_binding*); +#elif defined(__STDC__) +extern bool_t xdr_ypbind_binding(XDR *, ypbind_binding*); +#else /* Old Style C */ +bool_t xdr_ypbind_binding(); +#endif /* Old Style C */ + + +struct ypbind_resp { + ypbind_resptype ypbind_status; + union { + u_int ypbind_error; + ypbind_binding ypbind_bindinfo; + } ypbind_resp_u; +}; +typedef struct ypbind_resp ypbind_resp; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_resp(XDR *, ypbind_resp*); +#elif defined(__STDC__) +extern bool_t xdr_ypbind_resp(XDR *, ypbind_resp*); +#else /* Old Style C */ +bool_t xdr_ypbind_resp(); +#endif /* Old Style C */ + +#define YPBIND_ERR_ERR 1 +#define YPBIND_ERR_NOSERV 2 +#define YPBIND_ERR_RESC 3 + +struct ypbind_setdom { + domainname ypsetdom_domain; + ypbind_binding ypsetdom_binding; + u_int ypsetdom_vers; +}; +typedef struct ypbind_setdom ypbind_setdom; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_setdom(XDR *, ypbind_setdom*); +#elif defined(__STDC__) +extern bool_t xdr_ypbind_setdom(XDR *, ypbind_setdom*); +#else /* Old Style C */ +bool_t xdr_ypbind_setdom(); +#endif /* Old Style C */ + + +#define YPPROG ((u_long)100004) +#define YPVERS ((u_long)2) + +#ifdef __cplusplus +#define YPPROC_NULL ((u_long)0) +extern "C" void * ypproc_null_2(void *, CLIENT *); +extern "C" void * ypproc_null_2_svc(void *, struct svc_req *); +#define YPPROC_DOMAIN ((u_long)1) +extern "C" bool_t * ypproc_domain_2(domainname *, CLIENT *); +extern "C" bool_t * ypproc_domain_2_svc(domainname *, struct svc_req *); +#define YPPROC_DOMAIN_NONACK ((u_long)2) +extern "C" bool_t * ypproc_domain_nonack_2(domainname *, CLIENT *); +extern "C" bool_t * ypproc_domain_nonack_2_svc(domainname *, struct svc_req *); +#define YPPROC_MATCH ((u_long)3) +extern "C" ypresp_val * ypproc_match_2(ypreq_key *, CLIENT *); +extern "C" ypresp_val * ypproc_match_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_FIRST ((u_long)4) +extern "C" ypresp_key_val * ypproc_first_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_key_val * ypproc_first_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_NEXT ((u_long)5) +extern "C" ypresp_key_val * ypproc_next_2(ypreq_key *, CLIENT *); +extern "C" ypresp_key_val * ypproc_next_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_XFR ((u_long)6) +extern "C" ypresp_xfr * ypproc_xfr_2(ypreq_xfr *, CLIENT *); +extern "C" ypresp_xfr * ypproc_xfr_2_svc(ypreq_xfr *, struct svc_req *); +#define YPPROC_CLEAR ((u_long)7) +extern "C" void * ypproc_clear_2(void *, CLIENT *); +extern "C" void * ypproc_clear_2_svc(void *, struct svc_req *); +#define YPPROC_ALL ((u_long)8) +extern "C" ypresp_all * ypproc_all_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_all * ypproc_all_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MASTER ((u_long)9) +extern "C" ypresp_master * ypproc_master_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_master * ypproc_master_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_ORDER ((u_long)10) +extern "C" ypresp_order * ypproc_order_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_order * ypproc_order_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MAPLIST ((u_long)11) +extern "C" ypresp_maplist * ypproc_maplist_2(domainname *, CLIENT *); +extern "C" ypresp_maplist * ypproc_maplist_2_svc(domainname *, struct svc_req *); + +#elif defined(__STDC__) +#define YPPROC_NULL ((u_long)0) +extern void * ypproc_null_2(void *, CLIENT *); +extern void * ypproc_null_2_svc(void *, struct svc_req *); +#define YPPROC_DOMAIN ((u_long)1) +extern bool_t * ypproc_domain_2(domainname *, CLIENT *); +extern bool_t * ypproc_domain_2_svc(domainname *, struct svc_req *); +#define YPPROC_DOMAIN_NONACK ((u_long)2) +extern bool_t * ypproc_domain_nonack_2(domainname *, CLIENT *); +extern bool_t * ypproc_domain_nonack_2_svc(domainname *, struct svc_req *); +#define YPPROC_MATCH ((u_long)3) +extern ypresp_val * ypproc_match_2(ypreq_key *, CLIENT *); +extern ypresp_val * ypproc_match_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_FIRST ((u_long)4) +extern ypresp_key_val * ypproc_first_2(ypreq_nokey *, CLIENT *); +extern ypresp_key_val * ypproc_first_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_NEXT ((u_long)5) +extern ypresp_key_val * ypproc_next_2(ypreq_key *, CLIENT *); +extern ypresp_key_val * ypproc_next_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_XFR ((u_long)6) +extern ypresp_xfr * ypproc_xfr_2(ypreq_xfr *, CLIENT *); +extern ypresp_xfr * ypproc_xfr_2_svc(ypreq_xfr *, struct svc_req *); +#define YPPROC_CLEAR ((u_long)7) +extern void * ypproc_clear_2(void *, CLIENT *); +extern void * ypproc_clear_2_svc(void *, struct svc_req *); +#define YPPROC_ALL ((u_long)8) +extern ypresp_all * ypproc_all_2(ypreq_nokey *, CLIENT *); +extern ypresp_all * ypproc_all_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MASTER ((u_long)9) +extern ypresp_master * ypproc_master_2(ypreq_nokey *, CLIENT *); +extern ypresp_master * ypproc_master_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_ORDER ((u_long)10) +extern ypresp_order * ypproc_order_2(ypreq_nokey *, CLIENT *); +extern ypresp_order * ypproc_order_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MAPLIST ((u_long)11) +extern ypresp_maplist * ypproc_maplist_2(domainname *, CLIENT *); +extern ypresp_maplist * ypproc_maplist_2_svc(domainname *, struct svc_req *); + +#else /* Old Style C */ +#define YPPROC_NULL ((u_long)0) +extern void * ypproc_null_2(); +extern void * ypproc_null_2_svc(); +#define YPPROC_DOMAIN ((u_long)1) +extern bool_t * ypproc_domain_2(); +extern bool_t * ypproc_domain_2_svc(); +#define YPPROC_DOMAIN_NONACK ((u_long)2) +extern bool_t * ypproc_domain_nonack_2(); +extern bool_t * ypproc_domain_nonack_2_svc(); +#define YPPROC_MATCH ((u_long)3) +extern ypresp_val * ypproc_match_2(); +extern ypresp_val * ypproc_match_2_svc(); +#define YPPROC_FIRST ((u_long)4) +extern ypresp_key_val * ypproc_first_2(); +extern ypresp_key_val * ypproc_first_2_svc(); +#define YPPROC_NEXT ((u_long)5) +extern ypresp_key_val * ypproc_next_2(); +extern ypresp_key_val * ypproc_next_2_svc(); +#define YPPROC_XFR ((u_long)6) +extern ypresp_xfr * ypproc_xfr_2(); +extern ypresp_xfr * ypproc_xfr_2_svc(); +#define YPPROC_CLEAR ((u_long)7) +extern void * ypproc_clear_2(); +extern void * ypproc_clear_2_svc(); +#define YPPROC_ALL ((u_long)8) +extern ypresp_all * ypproc_all_2(); +extern ypresp_all * ypproc_all_2_svc(); +#define YPPROC_MASTER ((u_long)9) +extern ypresp_master * ypproc_master_2(); +extern ypresp_master * ypproc_master_2_svc(); +#define YPPROC_ORDER ((u_long)10) +extern ypresp_order * ypproc_order_2(); +extern ypresp_order * ypproc_order_2_svc(); +#define YPPROC_MAPLIST ((u_long)11) +extern ypresp_maplist * ypproc_maplist_2(); +extern ypresp_maplist * ypproc_maplist_2_svc(); +#endif /* Old Style C */ + +#define YPPUSH_XFRRESPPROG ((u_long)0x40000000) +#define YPPUSH_XFRRESPVERS ((u_long)1) + +#ifdef __cplusplus +#define YPPUSHPROC_NULL ((u_long)0) +extern "C" void * yppushproc_null_1(void *, CLIENT *); +extern "C" void * yppushproc_null_1_svc(void *, struct svc_req *); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern "C" yppushresp_xfr * yppushproc_xfrresp_1(void *, CLIENT *); +extern "C" yppushresp_xfr * yppushproc_xfrresp_1_svc(void *, struct svc_req *); + +#elif defined(__STDC__) +#define YPPUSHPROC_NULL ((u_long)0) +extern void * yppushproc_null_1(void *, CLIENT *); +extern void * yppushproc_null_1_svc(void *, struct svc_req *); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern yppushresp_xfr * yppushproc_xfrresp_1(void *, CLIENT *); +extern yppushresp_xfr * yppushproc_xfrresp_1_svc(void *, struct svc_req *); + +#else /* Old Style C */ +#define YPPUSHPROC_NULL ((u_long)0) +extern void * yppushproc_null_1(); +extern void * yppushproc_null_1_svc(); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern yppushresp_xfr * yppushproc_xfrresp_1(); +extern yppushresp_xfr * yppushproc_xfrresp_1_svc(); +#endif /* Old Style C */ + +#define YPBINDPROG ((u_long)100007) +#define YPBINDVERS ((u_long)2) + +#ifdef __cplusplus +#define YPBINDPROC_NULL ((u_long)0) +extern "C" void * ypbindproc_null_2(void *, CLIENT *); +extern "C" void * ypbindproc_null_2_svc(void *, struct svc_req *); +#define YPBINDPROC_DOMAIN ((u_long)1) +extern "C" ypbind_resp * ypbindproc_domain_2(domainname *, CLIENT *); +extern "C" ypbind_resp * ypbindproc_domain_2_svc(domainname *, struct svc_req *); +#define YPBINDPROC_SETDOM ((u_long)2) +extern "C" void * ypbindproc_setdom_2(ypbind_setdom *, CLIENT *); +extern "C" void * ypbindproc_setdom_2_svc(ypbind_setdom *, struct svc_req *); + +#elif defined(__STDC__) +#define YPBINDPROC_NULL ((u_long)0) +extern void * ypbindproc_null_2(void *, CLIENT *); +extern void * ypbindproc_null_2_svc(void *, struct svc_req *); +#define YPBINDPROC_DOMAIN ((u_long)1) +extern ypbind_resp * ypbindproc_domain_2(domainname *, CLIENT *); +extern ypbind_resp * ypbindproc_domain_2_svc(domainname *, struct svc_req *); +#define YPBINDPROC_SETDOM ((u_long)2) +extern void * ypbindproc_setdom_2(ypbind_setdom *, CLIENT *); +extern void * ypbindproc_setdom_2_svc(ypbind_setdom *, struct svc_req *); + +#else /* Old Style C */ +#define YPBINDPROC_NULL ((u_long)0) +extern void * ypbindproc_null_2(); +extern void * ypbindproc_null_2_svc(); +#define YPBINDPROC_DOMAIN ((u_long)1) +extern ypbind_resp * ypbindproc_domain_2(); +extern ypbind_resp * ypbindproc_domain_2_svc(); +#define YPBINDPROC_SETDOM ((u_long)2) +extern void * ypbindproc_setdom_2(); +extern void * ypbindproc_setdom_2_svc(); +#endif /* Old Style C */ + +#endif /* !_YP_H_RPCGEN */ diff --git a/ypserv.tproj/ypdb.c b/ypserv.tproj/ypdb.c new file mode 100644 index 0000000..c9bd178 --- /dev/null +++ b/ypserv.tproj/ypdb.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "ypdb.h" + +#ifdef YPDB_PATCH +extern DBM *__hash_open(); +#else +extern DBM *__bt_open(); +#endif + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +#else + BTREEINFO info; + char path[MAXPATHLEN]; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + db = (DBM *)__bt_open(path, flags, mode, &info, 0); + return (db); +#endif +} + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open_suf(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + return ((DBM *)__hash_open(file, flags, mode, &info, 0)); +#else + BTREEINFO info; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + db = (DBM *)__bt_open(file, flags, mode, &info, 0); + return (db); +#endif +} + +extern void +ypdb_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_firstkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_nextkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_setkey(db, key) + DBM *db; + datum key; +{ + int status; + datum retdata; +#ifdef YPDB_PATCH + datum retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + while ((retkey.dptr != NULL) && + ((retkey.dsize != key.dsize) || + (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) { + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + }; + return (retkey); +#else + status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR); + if (status) + key.dptr = NULL; + return (key); +#endif +} + +/* + * Returns: + * 0 on success + * <0 failure + */ + +int +ypdb_delete(db, key) + DBM *db; + datum key; +{ + int status; + + status = (db->del)(db, (DBT *)&key, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if YPDB_INSERT and entry exists + */ + +int +ypdb_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0)); +} + diff --git a/ypserv.tproj/ypdb.h b/ypserv.tproj/ypdb.h new file mode 100644 index 0000000..45b0a7f --- /dev/null +++ b/ypserv.tproj/ypdb.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDB_H_ +#define _YPDB_H_ + +#ifndef _DB_H_ +#include +#endif + +#define YPDB_SUFFIX ".db" + +/* Flags to ypdb_store(). */ +#define YPDB_INSERT 0 +#define YPDB_REPLACE 1 + +#ifndef DATUM +typedef struct { + char *dptr; + int dsize; +} datum; +#define DATUM +#endif + +typedef DB DBM; + +__BEGIN_DECLS +void ypdb_close __P((DBM *)); +datum ypdb_fetch __P((DBM *, datum)); +datum ypdb_firstkey __P((DBM *)); +datum ypdb_nextkey __P((DBM *)); +datum ypdb_setkey __P((DBM *, datum)); +DBM *ypdb_open __P((const char *, int, int)); +DBM *ypdb_open_suf __P((const char *, int, int)); +int ypdb_store __P((DBM *, datum, datum, int)); +__END_DECLS + +#endif /* !_YPDB_H_ */ diff --git a/ypserv.tproj/ypdef.h b/ypserv.tproj/ypdef.h new file mode 100644 index 0000000..89970d7 --- /dev/null +++ b/ypserv.tproj/ypdef.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDEF_H_ +#define _YPDEF_H_ + +#define YP_DB_PATH "/var/yp" +#define YP_LAST_KEY "YP_LAST_MODIFIED" +#define YP_LAST_LEN (sizeof(YP_LAST_KEY)-1) +#define YP_INPUT_KEY "YP_INPUT_FILE" +#define YP_INPUT_LEN (sizeof(YP_INPUT_KEY)-1) +#define YP_OUTPUT_KEY "YP_OUTPUT_FILE" +#define YP_OUTPUT_LEN (sizeof(YP_OUTPUT_KEY)-1) +#define YP_MASTER_KEY "YP_MASTER_NAME" +#define YP_MASTER_LEN (sizeof(YP_MASTER_KEY)-1) +#define YP_DOMAIN_KEY "YP_DOMAIN_NAME" +#define YP_DOMAIN_LEN (sizeof(YP_DOMAIN_KEY)-1) +#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN" +#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1) +#define YP_SECURE_KEY "YP_SECURE" +#define YP_SECURE_LEN (sizeof(YP_SECURE_KEY)-1) + +#define MAX_LAST_LEN 10 +#define MAX_MASTER_LEN 255 +#define YP_HOSTNAME "hosts.byname" +#define YP_HOSTADDR "hosts.byaddr" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define YPXFR_PROC "/usr/sbin/ypxfr" +#define YPPUSH_PROC "/usr/sbin/yppush" +#define YPSERV_PID_PATH "/var/run/ypserv.pid" +#define YP_SECURENET_FILE "/var/yp/securenet" + +#endif /* !_YPDEF_H_ */ diff --git a/ypserv.tproj/yplog.c b/ypserv.tproj/yplog.c new file mode 100644 index 0000000..3460c9a --- /dev/null +++ b/ypserv.tproj/yplog.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplog.c,v 1.5 1997/08/09 22:44:04 maja Exp $ */ + +/* + * Copyright (c) 1996 Charles D. Cranor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * yplog.c: replacement yplog routines for + * Mats O Jansson's ypserv program, as added by + * Chuck Cranor. + */ + +#include +#include +#include +#include +#ifdef __STDC__ +#include +#else +#include +#endif +#include "yplog.h" + +static FILE *logfp = NULL; /* the log file */ + +/* + * yplog(): like a printf, but to the log file. does the flush + * and data for you. + */ + +void +#ifdef __STDC__ +yplog(const char *fmt, ...) +#else +yplog(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vyplog(fmt, ap); + va_end(ap); +} + +/* + * vyplog() support routine for yplog() + */ + +void +vyplog(fmt, ap) + register const char *fmt; + va_list ap; +{ + time_t t; + + if (logfp == NULL) + return; + (void)time(&t); + fprintf(logfp,"%.15s ", ctime(&t) + 4); + vfprintf(logfp, fmt, ap); + fprintf(logfp,"\n"); + fflush(logfp); +} + +/* + * open log + */ + +void +ypopenlog() +{ + static char logfn[] = "/var/yp/ypserv.log"; + + if (access(logfn, W_OK) == -1) + return; + logfp = fopen("/var/yp/ypserv.log", "a"); + if (logfp == NULL) + return; + yplog("yplog opened"); +} + +/* + * close log + */ + +void +ypcloselog() +{ + if (logfp) { + yplog("yplog closed"); + fclose(logfp); + logfp = NULL; + } +} diff --git a/ypserv.tproj/yplog.h b/ypserv.tproj/yplog.h new file mode 100644 index 0000000..dd9d6fb --- /dev/null +++ b/ypserv.tproj/yplog.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplog.h,v 1.3 1996/05/30 09:53:04 deraadt Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPLOG_H_ +#define _YPLOG_H_ + +__BEGIN_DECLS +void yplog __P((const char *, ...)); +void vyplog __P((const char *, _BSD_VA_LIST_)); +void ypopenlog __P((void)); +void ypcloselog __P((void)); +__END_DECLS + +#endif /* !_YPLOG_H_ */ diff --git a/ypserv.tproj/ypserv.acl b/ypserv.tproj/ypserv.acl new file mode 100644 index 0000000..afeb86f --- /dev/null +++ b/ypserv.tproj/ypserv.acl @@ -0,0 +1,44 @@ +# This is an example of an access control file to be used by ypserv. +# +# This file is parsed line by line. First match will terminate the check +# of the caller. +# + +############################################################################# +# This is the commands that will match a single host +# +# allow host +# deny host +# +# To process hostname gethostbyname is called. If the hostname has multiple +# ip-addresses all will be added (I hope). ip-address is processed by +# inet_aton. +allow host localhost +deny host jodie + +############################################################################# +# This is the commands that will match a network +# +# allow net [netmask ] +# deny net [netmask ] +# +# To process netname getnetbyname is called, and inet_aton is used for +# netnumber. inet_aton both access numbers as 255.255.255.0 and 0xffffff00. +# +# If netmask isn't given the parser will assume netmask from the first bits +# of the network number. So if the network is subneted the you have to add +# the netmask. In my case I've got the network 139.58.253.0 at home so too +# allow any of my computers to talk with the server I need the following line +# +allow net mojathome netmask 255.255.255.0 + +############################################################################# +# At last we have a command that will match any caller: +# +# allow all +# deny all +# + +# reject all connections +deny all + diff --git a/ypserv.tproj/ypserv.acl.5 b/ypserv.tproj/ypserv.acl.5 new file mode 100644 index 0000000..4e00b7b --- /dev/null +++ b/ypserv.tproj/ypserv.acl.5 @@ -0,0 +1,182 @@ +.\" $OpenBSD: ypserv.acl.5,v 1.6 1997/08/05 09:26:56 maja Exp $ +.\" Copyright (c) 1994 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.Dd July 2, 1994 +.Dt YPSERV.ACL 5 +.Os +.Sh NAME +.Nm ypserv.acl +.Nd +.Xr ypserv 8 +configuration file +.Sh DESCRIPTION +The +.Nm ypserv.acl +file controls which hosts can connect to the +.Nm YP +server. +.Pp +The format is more complex than the format for +.Xr securenet 5 . +The first two verbs on each line controls if the line will +.Nm allow +or +.Nm deny +access for a +.Nm host , +network +.Nm (net) +or +.Nm all +hosts. +.Pp +The +.Nm YP +server reads the configuration file and build a list in memory. This list +is processed from the beginning for every incomming request. As soon a +match is found in the list the search terminates and it returns success +or failure depending on +.Nm allow +or +.Nm deny . +If no match was found in the list success is returned. +.Pp +If access is denied every call will cause a +.Nm no such domain +error for the caller. +.Pp +Don't forget to allow localhost access if you want the machine running +.Nm ypserv +access it too. +.Pp +There is no default name for this file. Start +.Nm ypserv +with a +.Ar -a filename +to read a file with this format. +.Pp +The following different syntax can be used: +.Pp +< +.Nm allow|deny +> +.Nm host +< +.Nm hostname|ip-address +> +.Pp +If +.Nm hostname +has more than one ip address then all will be added to the list. +.Pp +< +.Nm allow|deny +> +.Nm net +< +.Nm netname|netnumber +> +.Op Nm netmask +.Pp +If +.Nm netmask +part of the command isn't given then the netmask will be assumed to be a +class A, B or C net depending on the net number. +.Pp +< +.Nm allow|deny +> +.Nm all +.Pp +A line containing one of these commands will always match any host. +.Sh EXAMPLES +.Pp +A configuration file might appear as follows: +.Bd -literal +# This is an example of an access control file to be used by ypserv. +# +# This file is parsed line by line. First match will terminate the check +# of the caller. +# + +########################################################################### +# This is the commands that will match a single host +# +# allow host +# deny host +# +# To process hostname gethostbyname is called. If the hostname has +# multiple ip-addresses all will be added (I hope). ip-address +# processed by inet_aton. +allow host localhost +deny host jodie + +########################################################################### +# This is the commands that will match a network +# +# allow net [netmask ] +# deny net [netmask ] +# +# To process netname getnetbyname is called, and inet_aton is used for +# netnumber. inet_aton both access numbers as 255.255.255.0 and 0xffffff00. +# +# If netmask isn't given the parser will assume netmask from the first bits +# of the network number. So if the network is subneted the you have to add +# the netmask. In my case I've got the network 139.58.253.0 at home so too +# allow any of my computers to talk with the server I need the following +# line +# +allow net mojathome netmask 255.255.255.0 + +########################################################################### +# At last we have a command that will match any caller: +# +# allow all +# deny all +# + +# reject all connections +deny all + +.Ed +.Sh FILES +.Bl -tag -width /var/yp/ypserv.acl -compact +.It Pa /var/yp/ypserv.acl +A +.Xr ypserv 8 +configuration file. +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr ypserv 8 , +.Xr securenet 5 +.Sh AUTHOR +Mats O Jansson + diff --git a/ypserv.tproj/ypserv.c b/ypserv.tproj/ypserv.c new file mode 100644 index 0000000..7089884 --- /dev/null +++ b/ypserv.tproj/ypserv.c @@ -0,0 +1,559 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: ypserv.c,v 1.12 1997/11/04 07:40:52 deraadt Exp $"; +#endif + +#include "yp.h" +#include "ypv1.h" +#include +#include /* getenv, exit */ +#include /* for pmap_unset */ +#include /* strcmp */ +#include +#include +#include +#include +#include /* TIOCNOTTY */ +#ifdef __cplusplus +#include /* getdtablesize, open */ +#endif /* __cplusplus */ +#include +#include +#include +#include +#include "acl.h" +#include "yplog.h" +#include "ypdef.h" +#include +#include /* for ioctl */ +#include /* for open */ + +#ifdef __STDC__ +#define SIG_PF void(*)(int) +#endif + +#ifdef DEBUG +#define RPC_SVC_FG +#endif + +#define _RPCSVC_CLOSEDOWN 120 +static int _rpcpmstart; /* Started by a port monitor ? */ +static int _rpcfdtype; /* Whether Stream or Datagram ? */ +static int _rpcsvcdirty; /* Still serving ? */ + +int usedns = FALSE; +char *progname = "ypserv"; +char *aclfile = NULL; + +void sig_child(); +void sig_hup(); + +/* in the RPC library */ +SVCXPRT *svcfd_create(int, u_int, u_int); + +static +void _msgout(char* msg) +{ +#ifdef RPC_SVC_FG + if (_rpcpmstart) + syslog(LOG_ERR, msg); + else + (void) fprintf(stderr, "%s\n", msg); +#else + syslog(LOG_ERR, msg); +#endif +} + +static void +closedown() +{ + if (_rpcsvcdirty == 0) { + extern fd_set svc_fdset; + static int size; + int i, openfd; + + if (_rpcfdtype == SOCK_DGRAM) + exit(0); + if (size == 0) { + size = getdtablesize(); + } + for (i = 0, openfd = 0; i < size && openfd < 2; i++) + if (FD_ISSET(i, &svc_fdset)) + openfd++; + if (openfd <= (_rpcpmstart?0:1)) + exit(0); + } + (void) alarm(_RPCSVC_CLOSEDOWN); +} + +static void +ypprog_1(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + domainname ypproc_domain_1_arg; + domainname ypproc_domain_nonack_1_arg; + yprequest ypproc_match_1_arg; + yprequest ypproc_first_1_arg; + yprequest ypproc_next_1_arg; + yprequest ypproc_poll_1_arg; + yprequest ypproc_push_1_arg; + yprequest ypproc_pull_1_arg; + yprequest ypproc_get_1_arg; + } argument; + char *result; + xdrproc_t xdr_argument, xdr_result; + char *(*local)(char *, struct svc_req *); + + _rpcsvcdirty = 1; + switch (rqstp->rq_proc) { + case YPOLDPROC_NULL: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) ypproc_null_1_svc; + break; + + case YPOLDPROC_DOMAIN: + xdr_argument = (xdrproc_t) xdr_domainname; + xdr_result = (xdrproc_t) xdr_bool; + local = (char *(*)(char *, struct svc_req *)) ypproc_domain_1_svc; + break; + + case YPOLDPROC_DOMAIN_NONACK: + xdr_argument = (xdrproc_t) xdr_domainname; + xdr_result = (xdrproc_t) xdr_bool; + local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_1_svc; + break; + + case YPOLDPROC_MATCH: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_ypresponse; + local = (char *(*)(char *, struct svc_req *)) ypproc_match_1_svc; + break; + + case YPOLDPROC_FIRST: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_ypresponse; + local = (char *(*)(char *, struct svc_req *)) ypproc_first_1_svc; + break; + + case YPOLDPROC_NEXT: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_ypresponse; + local = (char *(*)(char *, struct svc_req *)) ypproc_next_1_svc; + break; + + case YPOLDPROC_POLL: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_ypresponse; + local = (char *(*)(char *, struct svc_req *)) ypproc_poll_1_svc; + break; + + case YPOLDPROC_PUSH: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) ypproc_push_1_svc; + break; + + case YPOLDPROC_PULL: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) ypproc_pull_1_svc; + break; + + case YPOLDPROC_GET: + xdr_argument = (xdrproc_t) xdr_yprequest; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) ypproc_get_1_svc; + break; + + default: + svcerr_noproc(transp); + _rpcsvcdirty = 0; + return; + } + (void) memset((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) { + svcerr_decode(transp); + _rpcsvcdirty = 0; + return; + } + result = (*local)((char *)&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) { + _msgout("unable to free arguments"); + exit(1); + } + _rpcsvcdirty = 0; + return; +} + +static void +ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp) +{ + union { + domainname ypproc_domain_2_arg; + domainname ypproc_domain_nonack_2_arg; + ypreq_key ypproc_match_2_arg; + ypreq_nokey ypproc_first_2_arg; + ypreq_key ypproc_next_2_arg; + ypreq_xfr ypproc_xfr_2_arg; + ypreq_nokey ypproc_all_2_arg; + ypreq_nokey ypproc_master_2_arg; + ypreq_nokey ypproc_order_2_arg; + domainname ypproc_maplist_2_arg; + } argument; + char *result; + xdrproc_t xdr_argument, xdr_result; + char *(*local)(char *, struct svc_req *); + + _rpcsvcdirty = 1; + switch (rqstp->rq_proc) { + case YPPROC_NULL: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc; + break; + + case YPPROC_DOMAIN: + xdr_argument = (xdrproc_t) xdr_domainname; + xdr_result = (xdrproc_t) xdr_bool; + local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc; + break; + + case YPPROC_DOMAIN_NONACK: + xdr_argument = (xdrproc_t) xdr_domainname; + xdr_result = (xdrproc_t) xdr_bool; + local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc; + break; + + case YPPROC_MATCH: + xdr_argument = (xdrproc_t) xdr_ypreq_key; + xdr_result = (xdrproc_t) xdr_ypresp_val; + local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc; + break; + + case YPPROC_FIRST: + xdr_argument = (xdrproc_t) xdr_ypreq_nokey; + xdr_result = (xdrproc_t) xdr_ypresp_key_val; + local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc; + break; + + case YPPROC_NEXT: + xdr_argument = (xdrproc_t) xdr_ypreq_key; + xdr_result = (xdrproc_t) xdr_ypresp_key_val; + local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc; + break; + + case YPPROC_XFR: + xdr_argument = (xdrproc_t) xdr_ypreq_xfr; + xdr_result = (xdrproc_t) xdr_ypresp_xfr; + local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc; + break; + + case YPPROC_CLEAR: + xdr_argument = (xdrproc_t) xdr_void; + xdr_result = (xdrproc_t) xdr_void; + local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc; + break; + + case YPPROC_ALL: + xdr_argument = (xdrproc_t) xdr_ypreq_nokey; + xdr_result = (xdrproc_t) xdr_ypresp_all; + local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc; + break; + + case YPPROC_MASTER: + xdr_argument = (xdrproc_t) xdr_ypreq_nokey; + xdr_result = (xdrproc_t) xdr_ypresp_master; + local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc; + break; + + case YPPROC_ORDER: + xdr_argument = (xdrproc_t) xdr_ypreq_nokey; + xdr_result = (xdrproc_t) xdr_ypresp_order; + local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc; + break; + + case YPPROC_MAPLIST: + xdr_argument = (xdrproc_t) xdr_domainname; + xdr_result = (xdrproc_t) xdr_ypresp_maplist; + local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc; + break; + + default: + svcerr_noproc(transp); + _rpcsvcdirty = 0; + return; + } + (void) memset((char *)&argument, 0, sizeof (argument)); + if (!svc_getargs(transp, xdr_argument, (caddr_t) &argument)) { + svcerr_decode(transp); + _rpcsvcdirty = 0; + return; + } + result = (*local)((char *)&argument, rqstp); + if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { + svcerr_systemerr(transp); + } + if (!svc_freeargs(transp, xdr_argument, (caddr_t) &argument)) { + _msgout("unable to free arguments"); + exit(1); + } + _rpcsvcdirty = 0; + return; +} + +int +main (argc,argv) +int argc; +char *argv[]; +{ + register SVCXPRT *transp = NULL; + int sock; + int proto = 0; + struct sockaddr_in saddr; + int asize = sizeof (saddr); + int usage = 0; + int xflag = 0; + int allowv1 = 0; + int ch; + extern char *optarg; + + while ((ch = getopt(argc, argv, "1a:dx")) != -1) + switch (ch) { + case '1': + allowv1 = TRUE; + break; + case 'a': + aclfile = optarg; + break; + case 'd': + usedns = TRUE; + break; + case 'x': + xflag = TRUE; + break; + default: + usage++; + break; + } + + if (usage) { + (void)fprintf(stderr,"usage: %s [-a aclfile] [-d] [-x]\n",progname); + exit(1); + } + + if (geteuid() != 0) { + (void)fprintf(stderr,"%s: must be root to run.\n",progname); + exit(1); + } + + if (aclfile != NULL) { + (void)acl_init(aclfile); + } else { + (void)acl_securenet(YP_SECURENET_FILE); + } + if (xflag) { + exit(1); + }; + + if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { + int ssize = sizeof (int); + + if (saddr.sin_family != AF_INET) + exit(1); + if (getsockopt(0, SOL_SOCKET, SO_TYPE, + (char *)&_rpcfdtype, &ssize) == -1) + exit(1); + sock = 0; + _rpcpmstart = 1; + proto = 0; + openlog("ypserv", LOG_PID, LOG_DAEMON); + } else { +#ifndef RPC_SVC_FG + int size; + int pid, i; + + pid = fork(); + if (pid < 0) { + perror("cannot fork"); + exit(1); + } + if (pid) + exit(0); + size = getdtablesize(); + for (i = 0; i < size; i++) + (void) close(i); + i = open("/dev/console", 2); + (void) dup2(i, 1); + (void) dup2(i, 2); + i = open("/dev/tty", 2); + if (i >= 0) { + (void) ioctl(i, TIOCNOTTY, (char *)NULL); + (void) close(i); + } + openlog("ypserv", LOG_PID, LOG_DAEMON); +#endif + sock = RPC_ANYSOCK; + (void) pmap_unset(YPPROG, YPVERS); + (void) pmap_unset(YPPROG, YPOLDVERS); + } + + ypopenlog(); /* open log file */ + ypdb_init(); /* init db stuff */ + + chdir("/"); + + (void)signal(SIGCHLD, sig_child); + (void)signal(SIGHUP, sig_hup); + { FILE *pidfile = fopen(YPSERV_PID_PATH, "w"); + if (pidfile != NULL) { + fprintf(pidfile, "%d\n", getpid()); + fclose(pidfile); + } + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { + transp = svcudp_create(sock); + if (transp == NULL) { + _msgout("cannot create udp service."); + exit(1); + } + if (transp->xp_port >= IPPORT_RESERVED) { + _msgout("cannot allocate udp privileged port."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_UDP; + if (allowv1) { + if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { + _msgout("unable to register (YPPROG, YPOLDVERS, udp)."); + exit(1); + } + } + if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { + _msgout("unable to register (YPPROG, YPVERS, udp)."); + exit(1); + } + } + + if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { + if (_rpcpmstart) + transp = svcfd_create(sock, 0, 0); + else + transp = svctcp_create(sock, 0, 0); + if (transp == NULL) { + _msgout("cannot create tcp service."); + exit(1); + } + if (transp->xp_port >= IPPORT_RESERVED) { + _msgout("cannot allocate tcp privileged port."); + exit(1); + } + if (!_rpcpmstart) + proto = IPPROTO_TCP; + if (allowv1) { + if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { + _msgout("unable to register (YPPROG, YPOLDVERS, tcp)."); + exit(1); + } + } + if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { + _msgout("unable to register (YPPROG, YPVERS, tcp)."); + exit(1); + } + } + + if (transp == (SVCXPRT *)NULL) { + _msgout("could not create a handle"); + exit(1); + } + if (_rpcpmstart) { + (void) signal(SIGALRM, (SIG_PF) closedown); + (void) alarm(_RPCSVC_CLOSEDOWN); + } + svc_run(); + _msgout("svc_run returned"); + exit(1); + /* NOTREACHED */ +} + +void +sig_child() +{ + int save_errno = errno; + + while (wait3((int *)NULL, WNOHANG, (struct rusage *)NULL) > 0) + ; + errno = save_errno; +} + +void +sig_hup() +{ + acl_reset(); + if (aclfile != NULL) { + yplog("sig_hup: reread %s",aclfile); + (void)acl_init(aclfile); + } else { + yplog("sig_hup: reread %s",YP_SECURENET_FILE); + (void)acl_securenet(YP_SECURENET_FILE); + } +} diff --git a/ypserv.tproj/ypserv_db.c b/ypserv.tproj/ypserv_db.c new file mode 100644 index 0000000..b7b6469 --- /dev/null +++ b/ypserv.tproj/ypserv_db.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * Copyright (c) 1996 Charles D. Cranor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * and Charles D. Cranor. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: ypserv_db.c,v 1.13 1997/08/09 23:10:12 maja Exp $"; +#endif + +/* + * major revision/cleanup of Mats' version + * done by Chuck Cranor + * Jan 1996. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "yplog.h" +#include "ypdb.h" +#include "ypdef.h" + +LIST_HEAD(domainlist, opt_domain); /* LIST of domains */ +LIST_HEAD(maplist, opt_map); /* LIST of maps (in a domain) */ +CIRCLEQ_HEAD(mapq, opt_map); /* CIRCLEQ of maps (LRU) */ + +struct opt_map { + mapname map; /* map name (malloc'd) */ + DBM *db; /* database */ + struct opt_domain *dom; /* back ptr to our domain */ + int host_lookup; /* host lookup */ + int secure; /* secure map? */ + CIRCLEQ_ENTRY(opt_map) mapsq; /* map queue pointers */ + LIST_ENTRY(opt_map) mapsl; /* map list pointers */ +}; + +struct opt_domain { + domainname domain; /* domain name (malloc'd) */ + struct maplist dmaps; /* the domain's active maps */ + LIST_ENTRY(opt_domain) domsl; /* global linked list of domains */ +}; + + +struct domainlist doms; /* global list of domains */ +struct mapq maps; /* global queue of maps (LRU) */ + +extern int usedns; + +/* + * ypdb_init: init the queues and lists + */ + +void +ypdb_init() + +{ + LIST_INIT(&doms); + CIRCLEQ_INIT(&maps); +} + + +/* + * yp_private: + * Check if key is a YP private key. Return TRUE if it is and + * ypprivate is FALSE. + */ + +int +yp_private(key,ypprivate) + datum key; + int ypprivate; +{ +/* int result; */ + + if (ypprivate) + return (FALSE); + + if (key.dsize == 0 || key.dptr == NULL) + return (FALSE); + + if (key.dsize == YP_LAST_LEN && + strncmp(key.dptr,YP_LAST_KEY,YP_LAST_LEN) == 0) + return(TRUE); + if (key.dsize == YP_INPUT_LEN && + strncmp(key.dptr,YP_INPUT_KEY,YP_INPUT_LEN) == 0) + return(TRUE); + if (key.dsize == YP_OUTPUT_LEN && + strncmp(key.dptr,YP_OUTPUT_KEY,YP_OUTPUT_LEN) == 0) + return(TRUE); + if (key.dsize == YP_MASTER_LEN && + strncmp(key.dptr,YP_MASTER_KEY,YP_MASTER_LEN) == 0) + return(TRUE); + if (key.dsize == YP_DOMAIN_LEN && + strncmp(key.dptr,YP_DOMAIN_KEY,YP_DOMAIN_LEN) == 0) + return(TRUE); + if (key.dsize == YP_INTERDOMAIN_LEN && + strncmp(key.dptr,YP_INTERDOMAIN_KEY,YP_INTERDOMAIN_LEN) == 0) + return(TRUE); + if (key.dsize == YP_SECURE_LEN && + strncmp(key.dptr,YP_SECURE_KEY,YP_SECURE_LEN) == 0) + return(TRUE); + + return(FALSE); +} + +/* + * Close least recent used map. This routine is called when we have + * no more file descripotors free, or we want to close all maps. + */ + +void +ypdb_close_last() +{ + struct opt_map *last = maps.cqh_last; + + if (last == (void*)&maps) { + yplog(" ypdb_close_last: LRU list is empty!"); + return; + } + + CIRCLEQ_REMOVE(&maps, last, mapsq); /* remove from LRU circleq */ + LIST_REMOVE(last, mapsl); /* remove from domain list */ + +#ifdef DEBUG + yplog(" ypdb_close_last: closing map %s in domain %s [db=0x%x]", + last->map, last->dom->domain, last->db); +#endif + + ypdb_close(last->db); /* close DB */ + free(last->map); /* free map name */ + free(last); /* free map */ + + +} + +/* + * Close all open maps. + */ + +void +ypdb_close_all() +{ + +#ifdef DEBUG + yplog(" ypdb_close_all(): start"); +#endif + while (maps.cqh_first != (void *)&maps) { + ypdb_close_last(); + } +#ifdef DEBUG + yplog(" ypdb_close_all(): done"); +#endif +} + +/* + * Close Database if Open/Close Optimization isn't turned on. + */ + +void +ypdb_close_db(db) + DBM *db; +{ +#ifdef DEBUG + yplog(" ypdb_close_db(0x%x)", db); +#endif +#ifndef OPTDB + ypdb_close_all(); +#endif +} + +/* + * ypdb_open_db + */ + +DBM * +ypdb_open_db(domain, map, status, map_info) + domainname domain; + mapname map; + ypstat *status; + struct opt_map **map_info; +{ + char map_path[MAXPATHLEN]; + static char *domain_key = YP_INTERDOMAIN_KEY; + static char *secure_key = YP_SECURE_KEY; +/* struct stat finfo; */ + DBM *db; +/* int fd; */ + struct opt_domain *d = NULL; + struct opt_map *m = NULL; + datum k,v; +#ifdef OPTDB + int i; +#endif + /* + * check for preloaded domain, map + */ + + for (d = doms.lh_first ; d != NULL ; d = d->domsl.le_next) { + if (strcmp(domain, d->domain) == 0) break; + } + + if (d) { + for (m = d->dmaps.lh_first ; m != NULL ; m = m->mapsl.le_next) + if (strcmp(map, m->map) == 0) break; + } + + /* + * map found open? + */ + + if (m) { +#ifdef DEBUG + yplog(" ypdb_open_db: cached open: domain=%s, map=%s, db=0x%x", + domain, map, m->db); +#endif + CIRCLEQ_REMOVE(&maps, m, mapsq); /* adjust LRU queue */ + CIRCLEQ_INSERT_HEAD(&maps, m, mapsq); + *status = YP_TRUE; + return(m->db); + } + + /* Check for illegal charcaters */ + + if (strchr(domain, '/')) { + *status = YP_NODOM; + return (NULL); + } + if (strchr(map, '/')) { + *status = YP_NOMAP; + return (NULL); + } + + + /* + * open map + */ +#ifdef OPTDB + i = 0; + while (i == 0) { +#endif + snprintf(map_path, sizeof(map_path), "%s/%s/%s", YP_DB_PATH, + domain, map); + db = ypdb_open(map_path, O_RDONLY, 0444); +#ifdef OPTDB + if (db == NULL) { +#ifdef DEBUG + yplog(" ypdb_open_db: errno %d (%s)", + errno,sys_errlist[errno]); +#endif + if ((errno == ENFILE) || (errno == EMFILE)) { + ypdb_close_last(); + } else { + i = errno; + } + } else { + i = 4711; + } + }; +#endif + *status = YP_NOMAP; /* see note below */ + if (db == NULL) { + if (errno == ENOENT) { +#ifdef DEBUG + yplog(" ypdb_open_db: no map %s (domain=%s)", + map, domain); +#endif + return(NULL); + } +#ifdef DEBUG + yplog(" ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)", + map, domain); +#endif + return(NULL); + } + + /* + * note: status now YP_NOMAP + */ + + if (d == NULL) { /* allocate new domain? */ + d = (struct opt_domain *) malloc(sizeof(*d)); + if (d) d->domain = strdup(domain); + if (d == NULL || d->domain == NULL) { + yplog(" ypdb_open_db: MALLOC failed"); + ypdb_close(db); + if (d) free(d); + return(NULL); + } + LIST_INIT(&d->dmaps); + LIST_INSERT_HEAD(&doms, d, domsl); +#ifdef DEBUG + yplog(" ypdb_open_db: NEW DOMAIN %s", domain); +#endif + } + + /* + * m must be NULL since we couldn't find a map. allocate new one + */ + + m = (struct opt_map *) malloc(sizeof(*m)); + if (m) { + m->map = strdup(map); + } + if (m == NULL || m->map == NULL) { + if (m) free(m); + yplog(" ypdb_open_db: MALLOC failed"); + ypdb_close(db); + return(NULL); + } + m->db = db; + m->dom = d; + m->host_lookup = FALSE; + CIRCLEQ_INSERT_HEAD(&maps, m, mapsq); + LIST_INSERT_HEAD(&d->dmaps, m, mapsl); + if (strcmp(map, YP_HOSTNAME) == 0 || strcmp(map, YP_HOSTADDR) == 0) { + if (!usedns) { + k.dptr = domain_key; + k.dsize = YP_INTERDOMAIN_LEN; + v = ypdb_fetch(db,k); + if (v.dptr) m->host_lookup = TRUE; + } else { + m->host_lookup = TRUE; + } + } + m->secure = FALSE; + k.dptr = secure_key; + k.dsize = YP_SECURE_LEN; + v = ypdb_fetch(db,k); + if (v.dptr) m->secure = TRUE; + *status = YP_TRUE; + if (map_info) *map_info = m; +#ifdef DEBUG + yplog(" ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=0x%x", + domain, map, m->host_lookup, m->secure, m->db); +#endif + return(m->db); +} + +#if 0 +/* + * lookup host. Not needed for Rhapsody, lookupd does this stuff. + */ + +ypstat +lookup_host(nametable, host_lookup, db, keystr, result) + int nametable; + int host_lookup; + DBM *db; + char *keystr; + ypresp_val *result; +{ + struct hostent *host; + struct in_addr *addr_name; + struct in_addr addr_addr; + static char val[BUFSIZ+1]; /* match libc */ + static hostname[MAXHOSTNAMELEN]; + char tmpbuf[MAXHOSTNAMELEN + 20]; + char *v; + int l; + char *ptr; + + if (!host_lookup) return(YP_NOKEY); + + if ((_res.options & RES_INIT) == 0) + res_init(); + bcopy("b", _res.lookups, sizeof("b")); + + if (nametable) { + host = gethostbyname(keystr); + if (host == NULL || host->h_addrtype != AF_INET) + return(YP_NOKEY); + addr_name = (struct in_addr *) *host->h_addr_list; + v = val; + for (; host->h_addr_list[0] != NULL; host->h_addr_list++) { + addr_name = (struct in_addr *)host->h_addr_list[0]; + snprintf(tmpbuf,sizeof(tmpbuf), "%s %s\n", + inet_ntoa(*addr_name), host->h_name); + if (v - val + strlen(tmpbuf) + 1 > sizeof(val)) + break; + strcpy(v, tmpbuf); + v = v + strlen(tmpbuf); + } + result->val.valdat_val = val; + result->val.valdat_len = v - val; + return(YP_TRUE); + } + + inet_aton(keystr, &addr_addr); + host = gethostbyaddr((char *) &addr_addr, sizeof(addr_addr), AF_INET); + if (host == NULL) return(YP_NOKEY); + + strncpy((char *)hostname, host->h_name, sizeof(hostname) - 1); + hostname[sizeof(hostname) - 1] = '\0'; + host = gethostbyname((char *)hostname); + if (host == NULL) return(YP_NOKEY); + + l = 0; + for(; host->h_addr_list[0] != NULL; host->h_addr_list++) + if (!bcmp(host->h_addr_list[0], &addr_addr, sizeof(addr_addr))) + l++; + if (l == 0) { + yplog("lookup_host: address %s not listed for host %s\n", + inet_ntoa(addr_addr), hostname); + syslog(LOG_NOTICE, + "ypserv: address %s not listed for host %s\n", + inet_ntoa(addr_addr), hostname); + return(YP_NOKEY); + } + + snprintf(val,sizeof(val),"%s %s",keystr,host->h_name); + l = strlen(val); + v = val + l; + while ((ptr = *(host->h_aliases)) != NULL) { + l = strlen(ptr); + if ((v - val) + l + 1 > BUFSIZ) + break; + strcpy(v, " "); + v += 1; + strcpy(v, ptr); + v += l; + host->h_aliases++; + } + result->val.valdat_val = val; + result->val.valdat_len = v - val; + + return(YP_TRUE); +} +#endif + +ypresp_val +ypdb_get_record(domain, map, key, ypprivate) + domainname domain; + mapname map; + keydat key; + int ypprivate; +{ + static ypresp_val res; +/* static char keystr[YPMAXRECORD+1]; */ + DBM *db; + datum k,v; + int host_lookup; + struct opt_map *map_info = NULL; + + bzero((char *)&res, sizeof(res)); + + db = ypdb_open_db(domain, map, &res.stat, &map_info); + if (!db || res.stat < 0) + return(res); + if (map_info) + host_lookup = map_info->host_lookup; + + k.dptr = key.keydat_val; + k.dsize = key.keydat_len; + + if (yp_private(k,ypprivate)) { + res.stat = YP_NOKEY; + goto done; + } + + v = ypdb_fetch(db, k); + + /* lookupd does DNS resolution, not ypserv. */ + if (v.dptr == NULL) { + res.stat = YP_NOKEY; + res.val.valdat_val = NULL; + res.val.valdat_len = 0; + } else { + res.val.valdat_val = v.dptr; + res.val.valdat_len = v.dsize; + } + +done: + ypdb_close_db(db); + return(res); + +} + +ypresp_key_val +ypdb_get_first(domain, map, ypprivate) + domainname domain; + mapname map; + int ypprivate; +{ + static ypresp_key_val res; + DBM *db; + datum k,v; + + bzero((char *)&res, sizeof(res)); + + db = ypdb_open_db(domain, map, &res.stat, NULL); + + if (res.stat >= 0) { + + k = ypdb_firstkey(db); + + while (yp_private(k,ypprivate)) { + k = ypdb_nextkey(db); + }; + + if (k.dptr == NULL) { + res.stat = YP_NOKEY; + } else { + res.key.keydat_val = k.dptr; + res.key.keydat_len = k.dsize; + v = ypdb_fetch(db,k); + if (v.dptr == NULL) { + res.stat = YP_NOKEY; + } else { + res.val.valdat_val = v.dptr; + res.val.valdat_len = v.dsize; + } + } + } + + ypdb_close_db(db); + + return (res); +} + +ypresp_key_val +ypdb_get_next(domain, map, key, ypprivate) + domainname domain; + mapname map; + keydat key; + int ypprivate; +{ + static ypresp_key_val res; + DBM *db; + datum k,v,n; + + bzero((char *)&res, sizeof(res)); + + db = ypdb_open_db(domain, map, &res.stat, NULL); + + if (res.stat >= 0) { + + n.dptr = key.keydat_val; + n.dsize = key.keydat_len; + v.dptr = NULL; + v.dsize = 0; + k.dptr = NULL; + k.dsize = 0; + + n = ypdb_setkey(db,n); + + if (n.dptr != NULL) { + k = ypdb_nextkey(db); + } else { + k.dptr = NULL; + }; + + if (k.dptr != NULL) { + while (yp_private(k,ypprivate)) { + k = ypdb_nextkey(db); + }; + }; + + if (k.dptr == NULL) { + res.stat = YP_NOMORE; + } else { + res.key.keydat_val = k.dptr; + res.key.keydat_len = k.dsize; + v = ypdb_fetch(db,k); + if (v.dptr == NULL) { + res.stat = YP_NOMORE; + } else { + res.val.valdat_val = v.dptr; + res.val.valdat_len = v.dsize; + } + } + } + + ypdb_close_db(db); + + return (res); +} + +ypresp_order +ypdb_get_order(domain, map) + domainname domain; + mapname map; +{ + static ypresp_order res; + static char *order_key = YP_LAST_KEY; + char order[MAX_LAST_LEN+1]; + DBM *db; + datum k,v; + + bzero((char *)&res, sizeof(res)); + + db = ypdb_open_db(domain, map, &res.stat, NULL); + + if (res.stat >= 0) { + + k.dptr = order_key; + k.dsize = YP_LAST_LEN; + + v = ypdb_fetch(db,k); + if (v.dptr == NULL) { + res.stat = YP_NOKEY; + } else { + strncpy(order, v.dptr, v.dsize); + order[v.dsize] = '\0'; + res.ordernum = (u_int32_t)atol(order); + } + } + + ypdb_close_db(db); + + return (res); +} + +ypresp_master +ypdb_get_master(domain, map) + domainname domain; + mapname map; +{ + static ypresp_master res; + static char *master_key = YP_MASTER_KEY; + static char master[MAX_MASTER_LEN+1]; + DBM *db; + datum k,v; + + bzero((char *)&res, sizeof(res)); + + db = ypdb_open_db(domain, map, &res.stat, NULL); + + if (res.stat >= 0) { + + k.dptr = master_key; + k.dsize = YP_MASTER_LEN; + + v = ypdb_fetch(db,k); + if (v.dptr == NULL) { + res.stat = YP_NOKEY; + } else { + strncpy(master, v.dptr, v.dsize); + master[v.dsize] = '\0'; + res.peer = (peername) &master; + } + } + + ypdb_close_db(db); + + return (res); +} + +bool_t +ypdb_xdr_get_all(xdrs, req) + XDR *xdrs; + ypreq_nokey *req; +{ + static ypresp_all resp; + DBM *db; + datum k,v; + + bzero((char *)&resp, sizeof(resp)); + + /* + * open db, and advance past any private keys we may see + */ + + db = ypdb_open_db(req->domain, req->map, + &resp.ypresp_all_u.val.stat, NULL); + if (!db || resp.ypresp_all_u.val.stat < 0) + return(FALSE); + k = ypdb_firstkey(db); + while (yp_private(k,FALSE)) { + k = ypdb_nextkey(db); + }; + + while(1) { + + if (k.dptr == NULL) + break; + + v = ypdb_fetch(db,k); + + if (v.dptr == NULL) + break; + + resp.more = TRUE; + resp.ypresp_all_u.val.stat = YP_TRUE; + resp.ypresp_all_u.val.key.keydat_val = k.dptr; + resp.ypresp_all_u.val.key.keydat_len = k.dsize; + resp.ypresp_all_u.val.val.valdat_val = v.dptr; + resp.ypresp_all_u.val.val.valdat_len = v.dsize; + + if (!xdr_ypresp_all(xdrs, &resp)) { +#ifdef DEBUG + yplog(" ypdb_xdr_get_all: xdr_ypresp_all failed"); +#endif + return(FALSE); + } + + /* advance past private keys */ + k = ypdb_nextkey(db); + while (yp_private(k,FALSE)) { + k = ypdb_nextkey(db); + } + } + + bzero((char *)&resp, sizeof(resp)); + resp.ypresp_all_u.val.stat = YP_NOKEY; + resp.more = FALSE; + + if (!xdr_ypresp_all(xdrs, &resp)) { +#ifdef DEBUG + yplog(" ypdb_xdr_get_all: final xdr_ypresp_all failed"); +#endif + return(FALSE); + } + + ypdb_close_db(db); + + return (TRUE); +} + +int +ypdb_secure(domain, map) + domainname domain; + mapname map; +{ + static ypresp_val res; + DBM *db; + int secure; + struct opt_map *map_info = NULL; + + bzero((char *)&res, sizeof(res)); + secure = FALSE; + + db = ypdb_open_db(domain, map, &res.stat, &map_info); + if (!db || res.stat < 0) + return(secure); /* ? */ + if (map_info) + secure = map_info->secure; + + ypdb_close_db(db); + return(secure); +} + diff --git a/ypserv.tproj/ypserv_proc.c b/ypserv.tproj/ypserv_proc.c new file mode 100644 index 0000000..84accf6 --- /dev/null +++ b/ypserv.tproj/ypserv_proc.c @@ -0,0 +1,1061 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypserv_proc.c,v 1.14 1997/09/12 01:44:57 deraadt Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: ypserv_proc.c,v 1.14 1997/09/12 01:44:57 deraadt Exp $"; +#endif + +#include +#include "yp.h" +#include "ypv1.h" +#include +#include +#include +#include +#include +#include +#include "ypdb.h" +#include +#include +#include +#include +#include +#include +#include "yplog.h" +#include "ypdef.h" + +#ifdef DEBUG +#define YPLOG yplog +#else /* DEBUG */ +#define YPLOG if (!ok) yplog +#endif /* DEBUG */ + +extern ypresp_val ypdb_get_record(); +extern ypresp_key_val ypdb_get_first(); +extern ypresp_key_val ypdb_get_next(); +extern ypresp_order ypdb_get_order(); +extern ypresp_master ypdb_get_master(); +extern bool_t ypdb_xdr_get_all(); +extern void ypdb_close_all(); +extern int ypdb_secure(); + +static char *True = "true"; +static char *False = "FALSE"; +#define TORF(N) ((N) ? True : False) +void * +ypproc_null_2_svc(argp, rqstp) + void *argp; + struct svc_req *rqstp; +{ + static char *result; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + + YPLOG("null_2: caller=[%s].%d, auth_ok=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok)); + + if (!ok) { + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + result = NULL; + + return ((void *)&result); +} + +bool_t * +ypproc_domain_2_svc(argp, rqstp) + domainname *argp; + struct svc_req *rqstp; +{ + static bool_t result; /* is domain_served? */ + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + static char domain_path[MAXPATHLEN]; + struct stat finfo; + + if (strchr(*argp, '/')) + goto bail; + snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp); + result = (bool_t) ((stat(domain_path, &finfo) == 0) && + (finfo.st_mode & S_IFDIR)); + + YPLOG("domain_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), *argp, TORF(result)); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + return (&result); +} + +bool_t * +ypproc_domain_nonack_2_svc(argp, rqstp) + domainname *argp; + struct svc_req *rqstp; +{ + static bool_t result; /* is domain served? */ + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + static char domain_path[MAXPATHLEN]; + struct stat finfo; + + if (strchr(*argp, '/')) + goto bail; + snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp); + result = (bool_t) ((stat(domain_path, &finfo) == 0) && + (finfo.st_mode & S_IFDIR)); + + YPLOG( + "domain_nonack_2: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), + *argp, TORF(result)); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (!result) { + return(NULL); /* don't send nack */ + } + + return (&result); +} + +ypresp_val * +ypproc_match_2_svc(argp, rqstp) + ypreq_key *argp; + struct svc_req *rqstp; +{ + static ypresp_val res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure = ypdb_secure(argp->domain,argp->map); + + if (strchr(argp->domain, '/') || strchr(argp->map, '/')) + goto bail; + YPLOG( + "match_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.stat = YP_YPERR; + } else { + res = ypdb_get_record(argp->domain,argp->map,argp->key, FALSE); + } + +#ifdef DEBUG + yplog(" match2_status: %s", yperr_string(ypprot_err(res.stat))); +#endif + + return (&res); +} + +ypresp_key_val * +ypproc_first_2_svc(argp, rqstp) + ypreq_nokey *argp; + struct svc_req *rqstp; +{ + static ypresp_key_val res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure = ypdb_secure(argp->domain,argp->map); + + if (strchr(argp->domain, '/') || strchr(argp->map, '/')) + goto bail; + YPLOG( "first_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->domain, argp->map); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.stat = YP_YPERR; + } else { + res = ypdb_get_first(argp->domain,argp->map,FALSE); + } + +#ifdef DEBUG + yplog(" first2_status: %s", yperr_string(ypprot_err(res.stat))); +#endif + + return (&res); +} + +ypresp_key_val * +ypproc_next_2_svc(argp, rqstp) + ypreq_key *argp; + struct svc_req *rqstp; +{ + static ypresp_key_val res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure = ypdb_secure(argp->domain,argp->map); + + if (strchr(argp->domain, '/') || strchr(argp->map, '/')) + goto bail; + YPLOG( + "next_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->domain, argp->map, argp->key.keydat_len, argp->key.keydat_val); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.stat = YP_YPERR; + } else { + res = ypdb_get_next(argp->domain,argp->map,argp->key,FALSE); + } + +#ifdef DEBUG + yplog(" next2_status: %s", yperr_string(ypprot_err(res.stat))); +#endif + + return (&res); +} + +ypresp_xfr * +ypproc_xfr_2_svc(argp, rqstp) + ypreq_xfr *argp; + struct svc_req *rqstp; +{ + static ypresp_xfr res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + pid_t pid; + char tid[11]; + char prog[11]; + char port[11]; + char ypxfr_proc[] = YPXFR_PROC; + char *ipadd; + + bzero((char *)&res, sizeof(res)); + + YPLOG("xfr_2: caller=[%s].%d, auth_ok=%s, domain=%s, tid=%d, prog=%d", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), + argp->map_parms.domain, argp->transid, argp->prog); + YPLOG(" ipadd=%s, port=%d, map=%s", inet_ntoa(caller->sin_addr), + argp->port, argp->map_parms.map); + + if (strchr(argp->map_parms.domain, '/') || + strchr(argp->map_parms.map, '/') || + ntohs(caller->sin_port) >= IPPORT_RESERVED) { + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + snprintf(tid, sizeof(tid), "%d",argp->transid); + snprintf(prog, sizeof(prog), "%d", argp->prog); + snprintf(port, sizeof(port), "%d", argp->port); + ipadd = inet_ntoa(caller->sin_addr); + + pid = vfork(); + if (pid == -1) { + svcerr_systemerr(rqstp->rq_xprt); + return(NULL); + } + if (pid == 0) { + execl(ypxfr_proc, "ypxfr", "-d", argp->map_parms.domain, + "-C",tid, prog, ipadd, port, argp->map_parms.map, NULL); + _exit(1); + } + + /* + * XXX: fill in res + */ + return (&res); +} + +void * +ypproc_clear_2_svc(argp, rqstp) + void *argp; + struct svc_req *rqstp; +{ + static char *res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + + YPLOG( "clear_2: caller=[%s].%d, auth_ok=%s, opt=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), +#ifdef OPTDB + True +#else + False +#endif + ); + + if (ntohs(caller->sin_port) >= IPPORT_RESERVED) + ok = FALSE; + + if (!ok) { + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + res = NULL; + +#ifdef OPTDB + ypdb_close_all(); +#endif + + return ((void *)&res); +} + +ypresp_all * +ypproc_all_2_svc(argp, rqstp) + ypreq_nokey *argp; + struct svc_req *rqstp; +{ + static ypresp_all res; + pid_t pid; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure = ypdb_secure(argp->domain,argp->map); + + if (strchr(argp->domain, '/') || strchr(argp->map, '/')) + goto bail; + YPLOG( "all_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), argp->domain, argp->map); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + bzero((char *)&res, sizeof(res)); + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.ypresp_all_u.val.stat = YP_YPERR; + return(&res); + } + + pid = fork(); + + if (pid) { + + if (pid == -1) { + /* XXXCDC An error has occurred */ + } + + return(NULL); /* PARENT: continue */ + + } + /* CHILD: send result, then exit */ + + if (!svc_sendreply(rqstp->rq_xprt, ypdb_xdr_get_all, (char *) argp)) { + svcerr_systemerr(rqstp->rq_xprt); + } + + /* note: no need to free args, we are exiting */ + + exit(0); +} + +ypresp_master * +ypproc_master_2_svc(argp, rqstp) + ypreq_nokey *argp; + struct svc_req *rqstp; +{ + static ypresp_master res; + static peername nopeer = ""; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure = ypdb_secure(argp->domain,argp->map); + + if (strchr(argp->domain, '/') || strchr(argp->map, '/')) + goto bail; + YPLOG( "master_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), argp->domain, argp->map); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.stat = YP_YPERR; + } else { + res = ypdb_get_master(argp->domain,argp->map); + } + +#ifdef DEBUG + yplog(" master2_status: %s", yperr_string(ypprot_err(res.stat))); +#endif + + /* This code was added because a yppoll */ + /* from a sun crashed the server in xdr_string, trying */ + /* to access the peer through a NULL-pointer. yppoll in */ + /* this server start asking for order. If order is ok */ + /* then it will ask for master. SunOS 4 asks for both */ + /* always. I'm not sure this is the best place for the */ + /* fix, but for now it will do. xdr_peername or */ + /* xdr_string in ypserv_xdr.c may be a better place? */ + + if (res.peer == NULL) { + res.peer = nopeer; + } + + /* End of fix */ + + return (&res); +} + + +ypresp_order * +ypproc_order_2_svc(argp, rqstp) + ypreq_nokey *argp; + struct svc_req *rqstp; +{ + static ypresp_order res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure = ypdb_secure(argp->domain,argp->map); + + if (strchr(argp->domain, '/')) + goto bail; + YPLOG( "order_2: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), argp->domain, argp->map); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.stat = YP_YPERR; + } else if (strchr(argp->map, '/')) { + res.stat = YP_NOMAP; + } else { + res = ypdb_get_order(argp->domain,argp->map); + } + +#ifdef DEBUG + yplog(" order2_status: %s", yperr_string(ypprot_err(res.stat))); +#endif + + return (&res); +} + + +ypresp_maplist * +ypproc_maplist_2_svc(argp, rqstp) + domainname *argp; + struct svc_req *rqstp; +{ + static ypresp_maplist res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + static char domain_path[MAXPATHLEN]; + struct stat finfo; + DIR *dirp = NULL; + struct dirent *dp; + char *suffix; + ypstat status; + struct ypmaplist *m; + char *map_name; + + if (strchr(*argp, '/')) + goto bail; + YPLOG("maplist_2: caller=[%s].%d, auth_ok=%s, domain=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), + *argp); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + bzero((char *)&res, sizeof(res)); + + snprintf(domain_path,MAXPATHLEN, "%s/%s",YP_DB_PATH,*argp); + + status = YP_TRUE; + + res.maps = NULL; + + if (!((stat(domain_path, &finfo) == 0) && + ((finfo.st_mode & S_IFMT) == S_IFDIR))) + status = YP_NODOM; + + if (status >= 0) { + if ((dirp = opendir(domain_path)) == NULL) { + status = YP_NODOM; + } + } + + if (status >= 0) { + for(dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { + if ((!strcmp(dp->d_name, ".")) || + ((!strcmp(dp->d_name, ".."))) || + (dp->d_namlen < 4)) + continue; + suffix = (char *) &dp->d_name[dp->d_namlen-3]; + if (strcmp(suffix,".db") == 0) { + + if ((m = (struct ypmaplist *) + malloc((unsigned) sizeof(struct ypmaplist))) == NULL) { + status = YP_YPERR; + break; + } + + if ((map_name = (char *) + malloc((unsigned) dp->d_namlen - 2)) == NULL) { + status = YP_YPERR; + break; + } + + m->next = res.maps; + m->map = map_name; + res.maps = m; + strncpy(map_name, dp->d_name, dp->d_namlen - 3); + m->map[dp->d_namlen - 3] = '\0'; + + } + } + } + + if (dirp != NULL) { + closedir(dirp); + } + + res.stat = status; + +#ifdef DEBUG + yplog(" maplist_status: %s", yperr_string(ypprot_err(res.stat))); +#endif + + return (&res); +} + +void * +ypproc_null_1_svc(argp, rqstp) + void *argp; + struct svc_req *rqstp; +{ + static char *result; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + + YPLOG("null_1: caller=[%s].%d, auth_ok=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok)); + + if (!ok) { + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + result = NULL; + + return ((void *)&result); +} + +bool_t * +ypproc_domain_1_svc(argp, rqstp) + domainname *argp; + struct svc_req *rqstp; +{ + static bool_t result; /* is domain_served? */ + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + static char domain_path[MAXPATHLEN]; + struct stat finfo; + + if (strchr(*argp, '/')) + goto bail; + snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp); + result = (bool_t) ((stat(domain_path, &finfo) == 0) && + (finfo.st_mode & S_IFDIR)); + + YPLOG("domain_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), *argp, TORF(result)); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + return (&result); +} + +bool_t * +ypproc_domain_nonack_1_svc(argp, rqstp) + domainname *argp; + struct svc_req *rqstp; +{ + static bool_t result; /* is domain served? */ + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + static char domain_path[MAXPATHLEN]; + struct stat finfo; + + if (strchr(*argp, '/')) + goto bail; + snprintf(domain_path, sizeof(domain_path), "%s/%s", YP_DB_PATH, *argp); + result = (bool_t) ((stat(domain_path, &finfo) == 0) && + (finfo.st_mode & S_IFDIR)); + + YPLOG( + "domain_nonack_1: caller=[%s].%d, auth_ok=%s, domain=%s, served=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), TORF(ok), + *argp, TORF(result)); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (!result) { + return(NULL); /* don't send nack */ + } + + return (&result); +} + +ypresponse * +ypproc_match_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + static ypresponse res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + + if (strchr(argp->ypmatch_req_domain, '/') || + strchr(argp->ypmatch_req_map, '/')) + goto bail; + res.yp_resptype = YPMATCH_RESPTYPE; + res.ypmatch_resp_valptr = ""; + res.ypmatch_resp_valsize = 0; + + if (argp->yp_reqtype != YPMATCH_REQTYPE) { + res.ypmatch_resp_status = YP_BADARGS; + return(&res); + } + + secure = ypdb_secure(argp->ypmatch_req_domain, argp->ypmatch_req_map); + + YPLOG( + "match_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->ypmatch_req_domain, argp->ypmatch_req_map, + argp->ypmatch_req_keysize, argp->ypmatch_req_keyptr); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.ypmatch_resp_status = YP_YPERR; + } else { + res.ypmatch_resp_val = + ypdb_get_record(argp->ypmatch_req_domain, + argp->ypmatch_req_map, + argp->ypmatch_req_keydat, + FALSE); + } + +#ifdef DEBUG + yplog(" match1_status: %s", + yperr_string(ypprot_err(res.ypmatch_resp_status))); +#endif + + return (&res); +} + +ypresponse * +ypproc_first_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + static ypresponse res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + + if (strchr(argp->ypfirst_req_domain, '/') || + strchr(argp->ypfirst_req_map, '/')) + goto bail; + res.yp_resptype = YPFIRST_RESPTYPE; + res.ypfirst_resp_valptr = res.ypfirst_resp_keyptr = ""; + res.ypfirst_resp_valsize = res.ypfirst_resp_keysize = 0; + + if (argp->yp_reqtype != YPREQ_NOKEY) { + res.ypfirst_resp_status = YP_BADARGS; + return(&res); + } + + secure = ypdb_secure(argp->ypfirst_req_domain, argp->ypfirst_req_map); + + YPLOG( "first_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->ypfirst_req_domain, argp->ypfirst_req_map); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.ypfirst_resp_status = YP_YPERR; + } else { + res.ypfirst_resp_val = + ypdb_get_first(argp->ypfirst_req_domain, + argp->ypfirst_req_map, + FALSE); + } + +#ifdef DEBUG + yplog(" first1_status: %s", + yperr_string(ypprot_err(res.ypfirst_resp_status))); +#endif + + return (&res); +} + +ypresponse * +ypproc_next_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + static ypresponse res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + + if (strchr(argp->ypnext_req_domain, '/') || + strchr(argp->ypnext_req_map, '/')) + goto bail; + res.yp_resptype = YPNEXT_RESPTYPE; + res.ypnext_resp_valptr = res.ypnext_resp_keyptr = ""; + res.ypnext_resp_valsize = res.ypnext_resp_keysize = 0; + + if (argp->yp_reqtype != YPNEXT_REQTYPE) { + res.ypnext_resp_status = YP_BADARGS; + return(&res); + } + + secure = ypdb_secure(argp->ypnext_req_domain, argp->ypnext_req_map); + + YPLOG( + "next_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, key=%.*s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->ypnext_req_domain, argp->ypnext_req_map, + argp->ypnext_req_keysize, argp->ypnext_req_keyptr); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED)) { + res.ypnext_resp_status = YP_YPERR; + } else { + res.ypnext_resp_val = + ypdb_get_next(argp->ypnext_req_domain, + argp->ypnext_req_map, + argp->ypnext_req_keydat, + FALSE); + } + +#ifdef DEBUG + yplog(" next1_status: %s", + yperr_string(ypprot_err(res.ypnext_resp_status))); +#endif + + return (&res); +} + +ypresponse * +ypproc_poll_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + static ypresponse res; + ypresp_order order; + ypresp_master master; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + + if (strchr(argp->yppoll_req_domain, '/') || + strchr(argp->yppoll_req_map, '/')) + goto bail; + res.yp_resptype = YPPOLL_RESPTYPE; + res.yppoll_resp_domain = argp->yppoll_req_domain; + res.yppoll_resp_map = argp->yppoll_req_map; + res.yppoll_resp_ordernum = 0; + res.yppoll_resp_owner = ""; + + if (argp->yp_reqtype != YPPOLL_REQTYPE) { + return(&res); + } + + secure = ypdb_secure(argp->yppoll_req_domain, argp->yppoll_req_map); + + YPLOG( "poll_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->yppoll_req_domain, argp->yppoll_req_map); + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + if (!(secure && (ntohs(caller->sin_port) >= IPPORT_RESERVED))) { + order = ypdb_get_order(argp->yppoll_req_domain, + argp->yppoll_req_map); + master = ypdb_get_master(argp->yppoll_req_domain, + argp->yppoll_req_map); + res.yppoll_resp_ordernum = order.ordernum; + res.yppoll_resp_owner = master.peer; + } + +#ifdef DEBUG + yplog(" poll1_status: %s", "none"); +#endif + return (&res); +} + +void * +ypproc_push_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + pid_t pid; + char yppush_proc[] = YPPUSH_PROC; + + if (strchr(argp->yppush_req_domain, '/') || + strchr(argp->yppush_req_map, '/')) + goto bail; + if (argp->yp_reqtype != YPPUSH_REQTYPE) { + return(NULL); + } + + secure = ypdb_secure(argp->yppush_req_domain, argp->yppush_req_map); + + YPLOG( "push_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->yppush_req_domain, argp->yppush_req_map); + + if (ntohs(caller->sin_port) >= IPPORT_RESERVED) + ok = FALSE; + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + pid = vfork(); + if (pid == -1) { + svcerr_systemerr(rqstp->rq_xprt); + return(NULL); + } + if (pid == 0) { + execl(yppush_proc, "yppush", "-d", argp->yppush_req_domain, + argp->yppush_req_map, NULL); + _exit(1); + } + + return (NULL); +} + +void * +ypproc_pull_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + pid_t pid; + char ypxfr_proc[] = YPXFR_PROC; + + if (strchr(argp->yppull_req_domain, '/') || + strchr(argp->yppull_req_map, '/')) + goto bail; + if (argp->yp_reqtype != YPPULL_REQTYPE) { + return(NULL); + } + + secure = ypdb_secure(argp->yppull_req_domain, argp->yppull_req_map); + + YPLOG( "pull_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->yppull_req_domain, argp->yppull_req_map); + + if (ntohs(caller->sin_port) >= IPPORT_RESERVED) + ok = FALSE; + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + pid = vfork(); + if (pid == -1) { + svcerr_systemerr(rqstp->rq_xprt); + return(NULL); + } + if (pid == 0) { + execl(ypxfr_proc, "ypxfr", "-d", argp->yppull_req_domain, + argp->yppull_req_map, NULL); + _exit(1); + } + + return (NULL); +} + +void * +ypproc_get_1_svc(argp, rqstp) + yprequest *argp; + struct svc_req *rqstp; +{ + char *res; + struct sockaddr_in *caller = svc_getcaller(rqstp->rq_xprt); + int ok = acl_check_host(&caller->sin_addr); + int secure; + pid_t pid; + char ypxfr_proc[] = YPXFR_PROC; + + if (strchr(argp->ypget_req_domain, '/') || + strchr(argp->ypget_req_map, '/')) + goto bail; + if (argp->yp_reqtype != YPGET_REQTYPE) { + return(NULL); + } + + secure = ypdb_secure(argp->ypget_req_domain, argp->ypget_req_map); + + YPLOG( "get_1: caller=[%s].%d, auth_ok=%s, secure=%s, domain=%s, map=%s, owner=%s", + inet_ntoa(caller->sin_addr), ntohs(caller->sin_port), + TORF(ok), TORF(secure), + argp->ypget_req_domain, argp->ypget_req_map, + argp->ypget_req_owner); + + if (ntohs(caller->sin_port) >= IPPORT_RESERVED) + ok = FALSE; + + if (!ok) { +bail: + svcerr_auth(rqstp->rq_xprt, AUTH_FAILED); + return(NULL); + } + + pid = vfork(); + if (pid == -1) { + svcerr_systemerr(rqstp->rq_xprt); + return(NULL); + } + if (pid == 0) { + execl(ypxfr_proc, "ypxfr", "-d", argp->ypget_req_domain, "-h", + argp->ypget_req_owner, argp->yppush_req_map, NULL); + _exit(1); + } + + return (NULL); +} diff --git a/ypserv.tproj/ypserv_xdr.c b/ypserv.tproj/ypserv_xdr.c new file mode 100644 index 0000000..2e1fb2a --- /dev/null +++ b/ypserv.tproj/ypserv_xdr.c @@ -0,0 +1,489 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "yp.h" +#ifndef lint +static char rcsid[] = "$OpenBSD: ypserv_xdr.c,v 1.3 1996/05/30 09:53:31 deraadt Exp $"; +#endif /* not lint */ + +__private_extern__ +bool_t +xdr_ypstat(xdrs, objp) + XDR *xdrs; + ypstat *objp; +{ + + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypxfrstat(xdrs, objp) + XDR *xdrs; + ypxfrstat *objp; +{ + + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_domainname(xdrs, objp) + XDR *xdrs; + domainname *objp; +{ + + register long *buf; + + if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_mapname(xdrs, objp) + XDR *xdrs; + mapname *objp; +{ + + register long *buf; + + if (!xdr_string(xdrs, objp, YPMAXMAP)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_peername(xdrs, objp) + XDR *xdrs; + peername *objp; +{ + + register long *buf; + + if (!xdr_string(xdrs, objp, YPMAXPEER)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_keydat(xdrs, objp) + XDR *xdrs; + keydat *objp; +{ + + register long *buf; + + if (!xdr_bytes(xdrs, (char **)&objp->keydat_val, (u_int *)&objp->keydat_len, YPMAXRECORD)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_valdat(xdrs, objp) + XDR *xdrs; + valdat *objp; +{ + + register long *buf; + + if (!xdr_bytes(xdrs, (char **)&objp->valdat_val, (u_int *)&objp->valdat_len, YPMAXRECORD)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypmap_parms(xdrs, objp) + XDR *xdrs; + ypmap_parms *objp; +{ + + register long *buf; + + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ordernum)) { + return (FALSE); + } + if (!xdr_peername(xdrs, &objp->peer)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypreq_key(xdrs, objp) + XDR *xdrs; + ypreq_key *objp; +{ + + register long *buf; + + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_keydat(xdrs, &objp->key)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypreq_nokey(xdrs, objp) + XDR *xdrs; + ypreq_nokey *objp; +{ + + register long *buf; + + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypreq_xfr(xdrs, objp) + XDR *xdrs; + ypreq_xfr *objp; +{ + + register long *buf; + + if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->prog)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->port)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypresp_val(xdrs, objp) + XDR *xdrs; + ypresp_val *objp; +{ + + register long *buf; + + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_valdat(xdrs, &objp->val)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypresp_key_val(xdrs, objp) + XDR *xdrs; + ypresp_key_val *objp; +{ + + register long *buf; + + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_valdat(xdrs, &objp->val)) { + return (FALSE); + } + if (!xdr_keydat(xdrs, &objp->key)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypresp_master(xdrs, objp) + XDR *xdrs; + ypresp_master *objp; +{ + + register long *buf; + + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_peername(xdrs, &objp->peer)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypresp_order(xdrs, objp) + XDR *xdrs; + ypresp_order *objp; +{ + + register long *buf; + + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ordernum)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypresp_all(xdrs, objp) + XDR *xdrs; + ypresp_all *objp; +{ + + register long *buf; + + if (!xdr_bool(xdrs, &objp->more)) { + return (FALSE); + } + switch (objp->more) { + case TRUE: + if (!xdr_ypresp_key_val(xdrs, &objp->ypresp_all_u.val)) { + return (FALSE); + } + break; + case FALSE: + break; + default: + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_xfr(xdrs, objp) + XDR *xdrs; + ypresp_xfr *objp; +{ + + register long *buf; + + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_ypxfrstat(xdrs, &objp->xfrstat)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypmaplist(xdrs, objp) + XDR *xdrs; + ypmaplist *objp; +{ + + register long *buf; + + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(ypmaplist), (xdrproc_t)xdr_ypmaplist)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypresp_maplist(xdrs, objp) + XDR *xdrs; + ypresp_maplist *objp; +{ + + register long *buf; + + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->maps, sizeof(ypmaplist), (xdrproc_t)xdr_ypmaplist)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yppush_status(xdrs, objp) + XDR *xdrs; + yppush_status *objp; +{ + + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yppushresp_xfr(xdrs, objp) + XDR *xdrs; + yppushresp_xfr *objp; +{ + + register long *buf; + + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_yppush_status(xdrs, &objp->status)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypbind_resptype(xdrs, objp) + XDR *xdrs; + ypbind_resptype *objp; +{ + + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypbind_binding(xdrs, objp) + XDR *xdrs; + ypbind_binding *objp; +{ + + register long *buf; + + int i; + if (!xdr_opaque(xdrs, objp->ypbind_binding_addr, 4)) { + return (FALSE); + } + if (!xdr_opaque(xdrs, objp->ypbind_binding_port, 2)) { + return (FALSE); + } + return (TRUE); +} + +__private_extern__ +bool_t +xdr_ypbind_resp(xdrs, objp) + XDR *xdrs; + ypbind_resp *objp; +{ + + register long *buf; + + if (!xdr_ypbind_resptype(xdrs, &objp->ypbind_status)) { + return (FALSE); + } + switch (objp->ypbind_status) { + case YPBIND_FAIL_VAL: + if (!xdr_u_int(xdrs, &objp->ypbind_resp_u.ypbind_error)) { + return (FALSE); + } + break; + case YPBIND_SUCC_VAL: + if (!xdr_ypbind_binding(xdrs, &objp->ypbind_resp_u.ypbind_bindinfo)) { + return (FALSE); + } + break; + default: + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypbind_setdom(xdrs, objp) + XDR *xdrs; + ypbind_setdom *objp; +{ + + register long *buf; + + if (!xdr_domainname(xdrs, &objp->ypsetdom_domain)) { + return (FALSE); + } + if (!xdr_ypbind_binding(xdrs, &objp->ypsetdom_binding)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ypsetdom_vers)) { + return (FALSE); + } + return (TRUE); +} diff --git a/ypserv.tproj/ypserv_xdr_v1.c b/ypserv.tproj/ypserv_xdr_v1.c new file mode 100644 index 0000000..3870f58 --- /dev/null +++ b/ypserv.tproj/ypserv_xdr_v1.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include "yp.h" +#include "ypv1.h" +#ifndef lint +static char rcsid[] = "$OpenBSD: ypserv_xdr_v1.c,v 1.1 1997/03/30 20:51:22 maja Exp $"; +#endif /* not lint */ + +bool_t +xdr_ypreqtype(xdrs, objp) + XDR *xdrs; + ypreqtype *objp; +{ + + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresptype(xdrs, objp) + XDR *xdrs; + ypresptype *objp; +{ + + register long *buf; + + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yprequest(xdrs, objp) + XDR *xdrs; + yprequest *objp; +{ + if (!xdr_ypreqtype(xdrs, &objp->yp_reqtype)) { + printf("error 1\n"); + return (FALSE); + } + switch (objp->yp_reqtype) { + case YPREQ_KEY: + if (!xdr_ypreq_key(xdrs, &objp->yp_reqbody.yp_req_keytype)) { + printf("error 2\n"); + return (FALSE); + } + break; + case YPREQ_NOKEY: + if (!xdr_ypreq_nokey(xdrs, &objp->yp_reqbody.yp_req_nokeytype)) { + printf("error 3\n"); + return (FALSE); + } + break; + case YPREQ_MAP_PARMS: + if (!xdr_ypmap_parms(xdrs, &objp->yp_reqbody.yp_req_map_parmstype)) { + printf("error 4\n"); + return (FALSE); + } + break; + default: + printf("error 5\n"); + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresponse(xdrs, objp) + XDR *xdrs; + ypresponse *objp; +{ + + register long *buf; + + if (!xdr_ypresptype(xdrs, &objp->yp_resptype)) { + return (FALSE); + } + switch (objp->yp_resptype) { + case YPRESP_VAL: + if (!xdr_ypresp_val(xdrs, &objp->yp_respbody.yp_resp_valtype)) { + return (FALSE); + } + break; + case YPRESP_KEY_VAL: + if (!xdr_ypresp_key_val(xdrs, &objp->yp_respbody.yp_resp_key_valtype)) { + return (FALSE); + } + break; + case YPRESP_MAP_PARMS: + if (!xdr_ypmap_parms(xdrs, &objp->yp_respbody.yp_resp_map_parmstype)) { + return (FALSE); + } + break; + default: + return (FALSE); + } + return (TRUE); +} + diff --git a/ypserv.tproj/ypv1.h b/ypserv.tproj/ypv1.h new file mode 100644 index 0000000..d378f83 --- /dev/null +++ b/ypserv.tproj/ypv1.h @@ -0,0 +1,264 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypv1.h,v 1.2 1997/07/25 20:12:31 mickey Exp $ */ + +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _YPV1_H_RPCGEN +#define _YPV1_H_RPCGEN + +#include + +#define YPOLDVERS ((u_long)1) + +enum ypreqtype { + YPREQ_KEY = 1, + YPREQ_NOKEY = 2, + YPREQ_MAP_PARMS = 3 +}; +typedef enum ypreqtype ypreqtype; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreqtype(XDR *, ypreqtype*); +#elif defined(__STDC__) +extern bool_t xdr_ypreqtype(XDR *, ypreqtype*); +#else /* Old Style C */ +bool_t xdr_ypreqtype(); +#endif /* Old Style C */ + +typedef struct { + ypreqtype yp_reqtype; + union { + struct ypreq_key yp_req_keytype; + struct ypreq_nokey yp_req_nokeytype; + struct ypmap_parms yp_req_map_parmstype; + }yp_reqbody; +} yprequest; +#ifdef __cplusplus +extern "C" bool_t xdr_yprequest(XDR *, yprequest*); +#elif defined(__STDC__) +extern bool_t xdr_yprequest(XDR *, yprequest*); +#else /* Old Style C */ +bool_t xdr_yprequest(); +#endif /* Old Style C */ + +#define YPMATCH_REQTYPE YPREQ_KEY +#define ypmatch_req_domain yp_reqbody.yp_req_keytype.domain +#define ypmatch_req_map yp_reqbody.yp_req_keytype.map +#define ypmatch_req_keydat yp_reqbody.yp_req_keytype.key +#define ypmatch_req_keyptr yp_reqbody.yp_req_keytype.key.keydat_val +#define ypmatch_req_keysize yp_reqbody.yp_req_keytype.key.keydat_len + +#define YPFIRST_REQTYPE YPREQ_NOKEY +#define ypfirst_req_domain yp_reqbody.yp_req_nokeytype.domain +#define ypfirst_req_map yp_reqbody.yp_req_nokeytype.map + +#define YPNEXT_REQTYPE YPREQ_KEY +#define ypnext_req_domain yp_reqbody.yp_req_keytype.domain +#define ypnext_req_map yp_reqbody.yp_req_keytype.map +#define ypnext_req_keydat yp_reqbody.yp_req_keytype.key +#define ypnext_req_keyptr yp_reqbody.yp_req_keytype.key.keydat_val +#define ypnext_req_keysize yp_reqbody.yp_req_keytype.key.keydat_len + +#define YPPUSH_REQTYPE YPREQ_NOKEY +#define yppush_req_domain yp_reqbody.yp_req_nokeytype.domain +#define yppush_req_map yp_reqbody.yp_req_nokeytype.map + +#define YPPULL_REQTYPE YPREQ_NOKEY +#define yppull_req_domain yp_reqbody.yp_req_nokeytype.domain +#define yppull_req_map yp_reqbody.yp_req_nokeytype.map + +#define YPPOLL_REQTYPE YPREQ_NOKEY +#define yppoll_req_domain yp_reqbody.yp_req_nokeytype.domain +#define yppoll_req_map yp_reqbody.yp_req_nokeytype.map + +#define YPGET_REQTYPE YPREQ_MAP_PARMS +#define ypget_req_domain yp_reqbody.yp_req_map_parmstype.domain +#define ypget_req_map yp_reqbody.yp_req_map_parmstype.map +#define ypget_req_ordernum yp_reqbody.yp_req_map_parmstype.ordernum +#define ypget_req_owner yp_reqbody.yp_req_map_parmstype.peer + +enum ypresptype { + YPRESP_VAL = 1, + YPRESP_KEY_VAL = 2, + YPRESP_MAP_PARMS = 3 +}; +typedef enum ypresptype ypresptype; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresptype(XDR *, ypresptype*); +#elif defined(__STDC__) +extern bool_t xdr_ypresptype(XDR *, ypresptype*); +#else /* Old Style C */ +bool_t xdr_ypresptype(); +#endif /* Old Style C */ + +typedef struct { + ypresptype yp_resptype; + union { + struct ypresp_val yp_resp_valtype; + struct ypresp_key_val yp_resp_key_valtype; + struct ypmap_parms yp_resp_map_parmstype; + } yp_respbody; +} ypresponse; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresponse(XDR *, ypresponse*); +#elif defined(__STDC__) +extern bool_t xdr_ypresponse(XDR *, ypresponse*); +#else /* Old Style C */ +bool_t xdr_ypresponse(); +#endif /* Old Style C */ + +#define YPMATCH_RESPTYPE YPRESP_VAL +#define ypmatch_resp_status yp_respbody.yp_resp_valtype.stat +#define ypmatch_resp_val yp_respbody.yp_resp_valtype +#define ypmatch_resp_valdat yp_respbody.yp_resp_valtype.val +#define ypmatch_resp_valptr yp_respbody.yp_resp_valtype.val.valdat_val +#define ypmatch_resp_valsize yp_respbody.yp_resp_valtype.val.valdat_len + +#define YPFIRST_RESPTYPE YPRESP_KEY_VAL +#define ypfirst_resp_status yp_respbody.yp_resp_key_valtype.stat +#define ypfirst_resp_keydat yp_respbody.yp_resp_key_valtype.key +#define ypfirst_resp_keyptr yp_respbody.yp_resp_key_valtype.key.keydat_val +#define ypfirst_resp_keysize yp_respbody.yp_resp_key_valtype.key.keydat_len +#define ypfirst_resp_val yp_respbody.yp_resp_key_valtype +#define ypfirst_resp_valdat yp_respbody.yp_resp_key_valtype.val +#define ypfirst_resp_valptr yp_respbody.yp_resp_key_valtype.val.valdat_val +#define ypfirst_resp_valsize yp_respbody.yp_resp_key_valtype.val.valdat_len + +#define YPNEXT_RESPTYPE YPRESP_KEY_VAL +#define ypnext_resp_status yp_respbody.yp_resp_key_valtype.stat +#define ypnext_resp_keydat yp_respbody.yp_resp_key_valtype.key +#define ypnext_resp_keyptr yp_respbody.yp_resp_key_valtype.key.keydat_val +#define ypnext_resp_keysize yp_respbody.yp_resp_key_valtype.key.keydat_len +#define ypnext_resp_val yp_respbody.yp_resp_key_valtype +#define ypnext_resp_valdat yp_respbody.yp_resp_key_valtype.val +#define ypnext_resp_valptr yp_respbody.yp_resp_key_valtype.val.valdat_val +#define ypnext_resp_valsize yp_respbody.yp_resp_key_valtype.val.valdat_len + +#define YPPOLL_RESPTYPE YPRESP_MAP_PARMS +#define yppoll_resp_domain yp_respbody.yp_resp_map_parmstype.domain +#define yppoll_resp_map yp_respbody.yp_resp_map_parmstype.map +#define yppoll_resp_ordernum yp_respbody.yp_resp_map_parmstype.ordernum +#define yppoll_resp_owner yp_respbody.yp_resp_map_parmstype.peer + +#ifdef __cplusplus +#define YPOLDPROC_NULL ((u_long)0) +extern "C" void * ypproc_null_1(void *, CLIENT *); +extern "C" void * ypproc_null_1_svc(void *, struct svc_req *); +#define YPOLDPROC_DOMAIN ((u_long)1) +extern "C" bool_t * ypproc_domain_1(domainname *, CLIENT *); +extern "C" bool_t * ypproc_domain_1_svc(domainname *, struct svc_req *); +#define YPOLDPROC_DOMAIN_NONACK ((u_long)2) +extern "C" bool_t * ypproc_domain_nonack_1(domainname *, CLIENT *); +extern "C" bool_t * ypproc_domain_nonack_1_svc(domainname *, struct svc_req *); +#define YPOLDPROC_MATCH ((u_long)3) +extern "C" ypresponse * ypproc_match_1(yprequest *, CLIENT *); +extern "C" ypresponse * ypproc_match_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_FIRST ((u_long)4) +extern "C" ypresponse * ypproc_first_1(yprequest *, CLIENT *); +extern "C" ypresponse * ypproc_first_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_NEXT ((u_long)5) +extern "C" ypresponse * ypproc_next_1(yprequest *, CLIENT *); +extern "C" ypresponse * ypproc_next_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_POLL ((u_long)6) +extern "C" ypresponse * ypproc_poll_1(yprequest *, CLIENT *); +extern "C" ypresponse * ypproc_poll_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_PUSH ((u_long)7) +extern "C" void * ypproc_push_1(yprequest *, CLIENT *); +extern "C" void * ypproc_push_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_PULL ((u_long)8) +extern "C" void * ypproc_pull_1(yprequest *, CLIENT *); +extern "C" void * ypproc_pull_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_GET ((u_long)9) +extern "C" void * ypproc_get_1(yprequest *, CLIENT *); +extern "C" void * ypproc_get_1_svc(yprequest *, struct svc_req *); + +#elif defined(__STDC__) +#define YPOLDPROC_NULL ((u_long)0) +extern void * ypproc_null_1(void *, CLIENT *); +extern void * ypproc_null_1_svc(void *, struct svc_req *); +#define YPOLDPROC_DOMAIN ((u_long)1) +extern bool_t * ypproc_domain_1(domainname *, CLIENT *); +extern bool_t * ypproc_domain_1_svc(domainname *, struct svc_req *); +#define YPOLDPROC_DOMAIN_NONACK ((u_long)2) +extern bool_t * ypproc_domain_nonack_1(domainname *, CLIENT *); +extern bool_t * ypproc_domain_nonack_1_svc(domainname *, struct svc_req *); +#define YPOLDPROC_MATCH ((u_long)3) +extern ypresponse * ypproc_match_1(yprequest *, CLIENT *); +extern ypresponse * ypproc_match_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_FIRST ((u_long)4) +extern ypresponse * ypproc_first_1(yprequest *, CLIENT *); +extern ypresponse * ypproc_first_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_NEXT ((u_long)5) +extern ypresponse * ypproc_next_1(yprequest *, CLIENT *); +extern ypresponse * ypproc_next_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_POLL ((u_long)6) +extern ypresponse * ypproc_poll_1(yprequest *, CLIENT *); +extern ypresponse * ypproc_poll_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_PUSH ((u_long)7) +extern void * ypproc_push_1(yprequest *, CLIENT *); +extern void * ypproc_push_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_PULL ((u_long)8) +extern void * ypproc_pull_1(yprequest *, CLIENT *); +extern void * ypproc_pull_1_svc(yprequest *, struct svc_req *); +#define YPOLDPROC_GET ((u_long)9) +extern void * ypproc_get_1(yprequest *, CLIENT *); +extern void * ypproc_get_1_svc(yprequest *, struct svc_req *); + +#else /* Old Style C */ +#define YPOLDPROC_NULL ((u_long)0) +extern void * ypproc_null_1(); +extern void * ypproc_null_1_svc(); +#define YPOLDPROC_DOMAIN ((u_long)1) +extern bool_t * ypproc_domain_1(); +extern bool_t * ypproc_domain_1_svc(); +#define YPOLDPROC_DOMAIN_NONACK ((u_long)2) +extern bool_t * ypproc_domain_nonack_1(); +extern bool_t * ypproc_domain_nonack_1_svc(); +#define YPOLDPROC_MATCH ((u_long)3) +extern ypresponse * ypproc_match_1(); +extern ypresponse * ypproc_match_1_svc(); +#define YPOLDPROC_FIRST ((u_long)4) +extern ypresponse * ypproc_first_1(); +extern ypresponse * ypproc_first_1_svc(); +#define YPOLDPROC_NEXT ((u_long)5) +extern ypresponse * ypproc_next_1(); +extern ypresponse * ypproc_next_1_svc(); +#define YPOLDPROC_POLL ((u_long)6) +extern ypresponse * ypproc_poll_1(); +extern ypresponse * ypproc_poll_1_svc(); +#define YPOLDPROC_PUSH ((u_long)7) +extern void * ypproc_push_1(); +extern void * ypproc_push_1_svc(); +#define YPOLDPROC_PULL ((u_long)8) +extern void * ypproc_pull_1(); +extern void * ypproc_pull_1_svc(); +#define YPOLDPROC_GET ((u_long)9) +extern void * ypproc_get_1(); +extern void * ypproc_get_1_svc(); +#endif /* Old Style C */ + +#endif /* !_YPV1_H_RPCGEN */ diff --git a/ypset.tproj/Makefile b/ypset.tproj/Makefile new file mode 100644 index 0000000..7abe695 --- /dev/null +++ b/ypset.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypset + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ypset.c + +OTHERSRCS = Makefile.dist Makefile.preamble + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +WINDOWS_INSTALLDIR = /usr/sbin +PDO_UNIX_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypset.tproj/Makefile.dist b/ypset.tproj/Makefile.dist new file mode 100644 index 0000000..1cb38ca --- /dev/null +++ b/ypset.tproj/Makefile.dist @@ -0,0 +1,7 @@ +# from: @(#)Makefile 5.8 (Berkeley) 7/28/90 +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $ + +PROG= ypset +NOMAN= + +.include diff --git a/ypset.tproj/Makefile.preamble b/ypset.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/ypset.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/ypset.tproj/PB.project b/ypset.tproj/PB.project new file mode 100644 index 0000000..bbc1e0f --- /dev/null +++ b/ypset.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (ypset.c); + OTHER_SOURCES = (Makefile.dist, Makefile.preamble); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/sbin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypset; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/sbin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypset.tproj/ypset.c b/ypset.tproj/ypset.c new file mode 100644 index 0000000..cddc148 --- /dev/null +++ b/ypset.tproj/ypset.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "ypset.c,v 1.3 1993/06/12 00:02:37 deraadt Exp"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include + +extern bool_t xdr_domainname(); + +void +usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\typset [-h host ] [-d domain] server\n"); + exit(1); +} + +int +bind_tohost(sin, dom, server) +struct sockaddr_in *sin; +char *dom, *server; +{ + ypbind_setdom ypsd; + struct timeval tv; + struct hostent *hp; + CLIENT *client; + int sock; + u_short port; + int r; + unsigned long server_addr; + + if( (port=htons(getrpcport(server, YPPROG, YPPROC_NULL, IPPROTO_UDP))) == 0) { + fprintf(stderr, "%s not running ypserv.\n", server); + exit(1); + } + + tv.tv_sec = 15; + tv.tv_usec = 0; + sock = RPC_ANYSOCK; + client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock); + if (client==NULL) { + fprintf(stderr, "RPC error: can't create YPBIND client\n"); + return YP_YPERR; + } + client->cl_auth = authunix_create_default(); + + bzero(&ypsd, sizeof(struct ypbind_setdom)); + + + if( (hp = gethostbyname (server)) != NULL ) { + /* is this the most compatible way?? */ + bcopy(hp->h_addr_list[0], &ypsd.ypsetdom_binding.ypbind_binding_addr, 4); + } else if( (long)(server_addr = inet_addr (server)) == -1) { + fprintf(stderr, "can't find address for %s\n", server); + exit(1); + } else + bcopy (&server_addr, &ypsd.ypsetdom_binding.ypbind_binding_addr, 4); + + ypsd.ypsetdom_domain = dom; + + bcopy(&port, ypsd.ypsetdom_binding.ypbind_binding_port, 2); + ypsd.ypsetdom_vers = YPVERS; + + r = clnt_call(client, YPBINDPROC_SETDOM, + xdr_ypbind_setdom, &ypsd, xdr_void, NULL, tv); + if (r != RPC_SUCCESS) + { + fprintf(stderr, "Can't ypset for domain %s: %s \n", + dom, clnt_sperror(client, "setdomain")); + clnt_destroy(client); + return YP_YPERR; + } + clnt_destroy(client); + return 0; +} + +int +main(argc, argv) +char **argv; +{ + struct sockaddr_in sin; + struct hostent *hent; + extern char *optarg; + extern int optind; + char *domainname; + int c; + + yp_get_default_domain(&domainname); + + bzero(&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(0x7f000001); + + while( (c=getopt(argc, argv, "h:d:")) != -1) + switch(c) { + case 'd': + domainname = optarg; + break; + case 'h': + if( (sin.sin_addr.s_addr=inet_addr(optarg)) == -1) { + hent = gethostbyname(optarg); + if(hent==NULL) { + fprintf(stderr, "ypset: host %s unknown\n", + optarg); + exit(1); + } + bcopy(&hent->h_addr_list[0], &sin.sin_addr, + sizeof sin.sin_addr); + } + break; + default: + usage(); + } + + if(optind + 1 != argc ) + usage(); + + if (bind_tohost(&sin, domainname, argv[optind])) + exit(1); + exit(0); +} diff --git a/ypwhich.tproj/Makefile b/ypwhich.tproj/Makefile new file mode 100644 index 0000000..4eb6204 --- /dev/null +++ b/ypwhich.tproj/Makefile @@ -0,0 +1,48 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypwhich + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +CFILES = ypwhich.c + +OTHERSRCS = Makefile.dist Makefile.preamble ypwhich.1 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/bin +WINDOWS_INSTALLDIR = /usr/bin +PDO_UNIX_INSTALLDIR = /usr/bin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypwhich.tproj/Makefile.dist b/ypwhich.tproj/Makefile.dist new file mode 100644 index 0000000..9837ebe --- /dev/null +++ b/ypwhich.tproj/Makefile.dist @@ -0,0 +1,6 @@ +# from: @(#)Makefile 5.8 (Berkeley) 7/28/90 +# $Id: Makefile.dist,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $ + +PROG= ypwhich + +.include diff --git a/ypwhich.tproj/Makefile.preamble b/ypwhich.tproj/Makefile.preamble new file mode 100644 index 0000000..dc05194 --- /dev/null +++ b/ypwhich.tproj/Makefile.preamble @@ -0,0 +1,2 @@ +OTHER_GENERATED_OFILES = $(VERS_OFILE) +-include ../Makefile.include diff --git a/ypwhich.tproj/PB.project b/ypwhich.tproj/PB.project new file mode 100644 index 0000000..6bbaabd --- /dev/null +++ b/ypwhich.tproj/PB.project @@ -0,0 +1,36 @@ +{ + FILESTABLE = { + C_FILES = (); + H_FILES = (); + M_FILES = (); + OTHER_LINKED = (ypwhich.c); + OTHER_SOURCES = (Makefile.dist, Makefile.preamble, ypwhich.1); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + NEXTSTEP_BUILDDIR = ""; + NEXTSTEP_BUILDTOOL = /bin/make; + NEXTSTEP_COMPILEROPTIONS = ""; + NEXTSTEP_INSTALLDIR = /usr/bin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_LINKEROPTIONS = ""; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDDIR = ""; + PDO_UNIX_BUILDTOOL = /bin/make; + PDO_UNIX_COMPILEROPTIONS = ""; + PDO_UNIX_INSTALLDIR = /usr/bin; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_LINKEROPTIONS = ""; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypwhich; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDDIR = ""; + WINDOWS_BUILDTOOL = /bin/make; + WINDOWS_COMPILEROPTIONS = ""; + WINDOWS_INSTALLDIR = /usr/bin; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_LINKEROPTIONS = ""; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypwhich.tproj/ypwhich.1 b/ypwhich.tproj/ypwhich.1 new file mode 100644 index 0000000..5c466f2 --- /dev/null +++ b/ypwhich.tproj/ypwhich.1 @@ -0,0 +1,94 @@ +.\" +.\" Copyright (c) 1994 Christopher G. Demetriou +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Christopher G. Demetriou. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: ypwhich.1,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $ +.\" +.Dd February 23, 1994 +.Dt YPWHICH 1 +.Os +.Sh NAME +.Nm ypwhich +.Nd return hostname of YP server of map master +.Sh SYNOPSIS +.Nm ypwhich +.Op Fl d Ar domain +.Oo +.Op Fl t +.Fl m Op Ar mname +| +.Ar host +.Oc +.Nm ypmatch +.Fl x +.Sh DESCRIPTION +.Nm Ypmatch +tells which +.Tn YP +server supplies +.Tn YP +services to a client, or which is the master for a map. +If invoked without arguments, it gives the +.Tn YP +server for the local machine. +If +.Ar host +is specified, that machine is queried to find out +which +.Tn YP +server it is using. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl d Ar domain +Specify a domain other than the default domain. +.It Fl t +Inhibit translation of map nicknames +to their corresponding map names. +.It Fl m Op Ar mname +Find the master +.Tn YP +server for the named map. No +.Ar host +may be specified with the +.Fl m +option. +.Ar Mname +can be a map name or nickname. If +.Ar mname +is ommitted, +.Nm ypwhich +will produce a list of available maps. +.It Fl x +Display the map nickname table. +.El +.Sh SEE ALSO +.Xr ypset 8 , +.Xr yp 8 +.Sh AUTHOR +Theo De Raadt diff --git a/ypwhich.tproj/ypwhich.c b/ypwhich.tproj/ypwhich.c new file mode 100644 index 0000000..523e1d0 --- /dev/null +++ b/ypwhich.tproj/ypwhich.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$Id: ypwhich.c,v 1.1.1.1 1999/05/02 03:59:06 wsanchez Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include + +extern bool_t xdr_domainname(); + +struct ypalias { + char *alias, *name; +} ypaliases[] = { + { "passwd", "passwd.byname" }, + { "group", "group.byname" }, + { "networks", "networks.byaddr" }, + { "hosts", "hosts.byaddr" }, + { "protocols", "protocols.bynumber" }, + { "services", "services.byname" }, + { "aliases", "mail.aliases" }, + { "ethers", "ethers.byname" }, +}; +static int n_aliases = 8; + +void +usage() +{ + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\typwhich [-d domain] [[-t] -m [mname] | host]\n"); + fprintf(stderr, "\typwhich -x\n"); + exit(1); +} + + +/* + * Like yp_bind except can query a specific host + */ +int +bind_host(char *dom, struct sockaddr_in *sin) +{ + struct hostent *hent = NULL; + struct ypbind_resp ypbr; + struct timeval tv; + CLIENT *client; + int sock, r; + struct in_addr addr; + + sock = RPC_ANYSOCK; + tv.tv_sec = 15; + tv.tv_usec = 0; + client = clntudp_create(sin, YPBINDPROG, YPBINDVERS, tv, &sock); + if (client==NULL) + { + fprintf(stderr, "can't clntudp_create: %s\n", + yperr_string(YPERR_YPBIND)); + return YPERR_YPBIND; + } + + tv.tv_sec = 5; + tv.tv_usec = 0; + r = clnt_call(client, YPBINDPROC_DOMAIN, + xdr_domainname, &dom, xdr_ypbind_resp, &ypbr, tv); + + if (r != RPC_SUCCESS) + { + fprintf(stderr, "can't clnt_call: %s\n", yperr_string(YPERR_YPBIND)); + clnt_destroy(client); + return YPERR_YPBIND; + } + else + { + if (ypbr.ypbind_status != YPBIND_SUCC_VAL) + { + fprintf(stderr, "can't yp_bind: Reason: %s\n", + yperr_string(ypbr.ypbind_status)); + clnt_destroy(client); + return r; + } + } + + clnt_destroy(client); + + memmove(&addr, ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, 4); + + hent = gethostbyaddr((char *)&(addr.s_addr), sizeof(u_long), AF_INET); + if (hent != NULL) printf("%s\n", hent->h_name); + else printf("%s\n", inet_ntoa(addr)); + return 0; +} + +int +main(int argc, char *argv[]) +{ + char *domainname, *master, *map; + ypmaplist *ypml, *y; + extern char *optarg; + extern int optind; + struct hostent *hent; + struct sockaddr_in sin; + int notrans, mode, getmap; + int c, r, i; + + yp_get_default_domain(&domainname); + + map = NULL; + getmap = notrans = mode = 0; + while ((c = getopt(argc, argv, "xd:mt")) != -1) + { + switch(c) + { + case 'x': + for (i = 0; i < n_aliases; i++) + { + printf("Use \"%s\" for \"%s\"\n", + ypaliases[i].alias, + ypaliases[i].name); + } + exit(0); + + case 'd': + domainname = optarg; + break; + + case 't': + notrans++; + break; + + case 'm': + mode++; + break; + + default: + usage(); + } + } + + if (mode == 0) + { + switch(argc-optind) + { + case 0: + bzero(&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + + if (bind_host(domainname, &sin)) exit(1); + break; + + case 1: + bzero(&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = inet_addr(argv[optind]); + if (sin.sin_addr.s_addr == -1) + { + hent = gethostbyname(argv[optind]); + if (hent == NULL) + { + fprintf(stderr, "ypwhich: host %s unknown\n", + argv[optind]); + exit(1); + } + + bcopy((char *)hent->h_addr_list[0], + (char *)&sin.sin_addr, sizeof sin.sin_addr); + } + + if (bind_host(domainname, &sin)) exit(1); + break; + + default: + usage(); + } + + exit(0); + } + + if (argc-optind > 1) usage(); + + if (argv[optind]) + { + map = argv[optind]; + for (i = 0; (!notrans) && (i < n_aliases); i++) + { + if (!strcmp(map, ypaliases[i].alias)) map = ypaliases[i].name; + } + + r = yp_master(domainname, map, &master); + switch(r) + { + case 0: + printf("%s\n", master); + free(master); + break; + case YPERR_YPBIND: + fprintf(stderr, "ypwhich: not running ypbind\n"); + exit(1); + default: + fprintf(stderr, "Can't find master for map %s. Reason: %s\n", + map, yperr_string(r)); + exit(1); + } + exit(0); + } + + ypml = NULL; + r = yp_maplist(domainname, &ypml); + switch(r) + { + case 0: + while (ypml != NULL) + { + r = yp_master(domainname, ypml->map, &master); + switch(r) + { + case 0: + printf("%s %s\n", ypml->map, master); + free(master); + break; + default: + fprintf(stderr, + "YP: can't find the master of %s: Reason: %s\n", + ypml->map, yperr_string(r)); + break; + } + + y = ypml; + ypml = ypml->next; + free(y); + } + break; + + case YPERR_YPBIND: + fprintf(stderr, "ypwhich: not running ypbind\n"); + exit(1); + + default: + fprintf(stderr, "Can't get map list for domain %s. Reason: %s\n", + domainname, yperr_string(r)); + exit(1); + } + + exit(0); +} diff --git a/ypxfr.tproj/Makefile b/ypxfr.tproj/Makefile new file mode 100644 index 0000000..bec2e2c --- /dev/null +++ b/ypxfr.tproj/Makefile @@ -0,0 +1,49 @@ +# +# Generated by the NeXT Project Builder. +# +# NOTE: Do NOT change this file -- Project Builder maintains it. +# +# Put all of your customizations in files called Makefile.preamble +# and Makefile.postamble (both optional), and Makefile will include them. +# + +NAME = ypxfr + +PROJECTVERSION = 2.8 +PROJECT_TYPE = Tool + +HFILES = ypdb.h ypdef.h yplib_host.h yplog.h + +CFILES = ypdb.c yplib_host.c yplog.c ypxfr.c ypxfr_xdr.c + +OTHERSRCS = Makefile.preamble Makefile Makefile.postamble\ + ypxfr_1perday.sh ypxfr_1perhour.sh ypxfr_2perday.sh ypxfr.8 + + +MAKEFILEDIR = $(MAKEFILEPATH)/pb_makefiles +CODE_GEN_STYLE = DYNAMIC +MAKEFILE = tool.make +NEXTSTEP_INSTALLDIR = /usr/sbin +LIBS = +DEBUG_LIBS = $(LIBS) +PROF_LIBS = $(LIBS) + + + + +NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc +WINDOWS_OBJCPLUS_COMPILER = $(DEVDIR)/gcc +PDO_UNIX_OBJCPLUS_COMPILER = $(NEXTDEV_BIN)/gcc +NEXTSTEP_JAVA_COMPILER = /usr/bin/javac +WINDOWS_JAVA_COMPILER = $(JDKBINDIR)/javac.exe +PDO_UNIX_JAVA_COMPILER = $(NEXTDEV_BIN)/javac + +include $(MAKEFILEDIR)/platform.make + +-include Makefile.preamble + +include $(MAKEFILEDIR)/$(MAKEFILE) + +-include Makefile.postamble + +-include Makefile.dependencies diff --git a/ypxfr.tproj/Makefile.postamble b/ypxfr.tproj/Makefile.postamble new file mode 100644 index 0000000..509e7f5 --- /dev/null +++ b/ypxfr.tproj/Makefile.postamble @@ -0,0 +1,101 @@ +############################################################################### +# Makefile.postamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile, which is imported after all other makefiles, to +# override attributes for a project's Makefile environment. This allows you +# to take advantage of the environment set up by the other Makefiles. +# You can also define custom rules at the end of this file. +# +############################################################################### +# +# These variables are exported by the standard makefiles and can be +# used in any customizations you make. They are *outputs* of +# the Makefiles and should be used, not set. +# +# PRODUCTS: products to install. All of these products will be placed in +# the directory $(DSTROOT)$(INSTALLDIR) +# GLOBAL_RESOURCE_DIR: The directory to which resources are copied. +# LOCAL_RESOURCE_DIR: The directory to which localized resources are copied. +# OFILE_DIR: Directory into which .o object files are generated. +# DERIVED_SRC_DIR: Directory used for all other derived files +# +# ALL_CFLAGS: flags to pass when compiling .c files +# ALL_MFLAGS: flags to pass when compiling .m files +# ALL_CCFLAGS: flags to pass when compiling .cc, .cxx, and .C files +# ALL_MMFLAGS: flags to pass when compiling .mm, .mxx, and .M files +# ALL_PRECOMPFLAGS: flags to pass when precompiling .h files +# ALL_LDFLAGS: flags to pass when linking object files +# ALL_LIBTOOL_FLAGS: flags to pass when libtooling object files +# ALL_PSWFLAGS: flags to pass when processing .psw and .pswm (pswrap) files +# ALL_RPCFLAGS: flags to pass when processing .rpc (rpcgen) files +# ALL_YFLAGS: flags to pass when processing .y (yacc) files +# ALL_LFLAGS: flags to pass when processing .l (lex) files +# +# NAME: name of application, bundle, subproject, palette, etc. +# LANGUAGE: langage in which the project is written (default "English") +# LOCAL_RESOURCES: localized resources (e.g. nib's, images) of project +# GLOBAL_RESOURCES: non-localized resources of project +# +# SRCROOT: base directory in which to place the new source files +# SRCPATH: relative path from SRCROOT to present subdirectory +# +# INSTALLDIR: Directory the product will be installed into by 'install' target +# PUBLIC_HDR_INSTALLDIR: where to install public headers. Don't forget +# to prefix this with DSTROOT when you use it. +# PRIVATE_HDR_INSTALLDIR: where to install private headers. Don't forget +# to prefix this with DSTROOT when you use it. +# +# EXECUTABLE_EXT: Executable extension for the platform (i.e. .exe on Windows) +# +############################################################################### + +# Some compiler flags can be overridden here for certain build situations. +# +# WARNING_CFLAGS: flag used to set warning level (defaults to -Wmost) +# DEBUG_SYMBOLS_CFLAGS: debug-symbol flag passed to all builds (defaults +# to -g) +# DEBUG_BUILD_CFLAGS: flags passed during debug builds (defaults to -DDEBUG) +# OPTIMIZE_BUILD_CFLAGS: flags passed during optimized builds (defaults +# to -O) +# PROFILE_BUILD_CFLAGS: flags passed during profile builds (defaults +# to -pg -DPROFILE) +# LOCAL_DIR_INCLUDE_DIRECTIVE: flag used to add current directory to +# the include path (defaults to -I.) +# DEBUG_BUILD_LDFLAGS, OPTIMIZE_BUILD_LDFLAGS, PROFILE_BUILD_LDFLAGS: flags +# passed to ld/libtool (defaults to nothing) + + +# Library and Framework projects only: +# INSTALL_NAME_DIRECTIVE: This directive ensures that executables linked +# against the framework will run against the correct version even if +# the current version of the framework changes. You may override this +# to "" as an alternative to using the DYLD_LIBRARY_PATH during your +# development cycle, but be sure to restore it before installing. + + +# Ownership and permissions of files installed by 'install' target + +#INSTALL_AS_USER = root + # User/group ownership +#INSTALL_AS_GROUP = wheel + # (probably want to set both of these) +#INSTALL_PERMISSIONS = + # If set, 'install' chmod's executable to this + + +# Options to strip. Note: -S strips debugging symbols (executables can be stripped +# down further with -x or, if they load no bundles, with no options at all). + +#STRIPFLAGS = -S +STRIPFLAGS = + + +######################################################################### +# Put rules to extend the behavior of the standard Makefiles here. Include them in +# the dependency tree via cvariables like AFTER_INSTALL in the Makefile.preamble. +# +# You should avoid redefining things like "install" or "app", as they are +# owned by the top-level Makefile API and no context has been set up for where +# derived files should go. +# diff --git a/ypxfr.tproj/Makefile.preamble b/ypxfr.tproj/Makefile.preamble new file mode 100644 index 0000000..83f25c7 --- /dev/null +++ b/ypxfr.tproj/Makefile.preamble @@ -0,0 +1,123 @@ +############################################################################### +# Makefile.preamble +# Copyright 1997, Apple Computer, Inc. +# +# Use this makefile for configuring the standard application makefiles +# associated with ProjectBuilder. It is included before the main makefile. +# In Makefile.preamble you set attributes for a project, so they are available +# to the project's makefiles. In contrast, you typically write additional rules or +# override built-in behavior in the Makefile.postamble. +# +# Each directory in a project tree (main project plus subprojects) should +# have its own Makefile.preamble and Makefile.postamble. +############################################################################### +# +# Before the main makefile is included for this project, you may set: +# +# MAKEFILEDIR: Directory in which to find $(MAKEFILE) +# MAKEFILE: Top level mechanism Makefile (e.g., app.make, bundle.make) + +# Compiler/linker flags added to the defaults: The OTHER_* variables will be +# inherited by all nested sub-projects, but the LOCAL_ versions of the same +# variables will not. Put your -I, -D, -U, and -L flags in ProjectBuilder's +# Build Attributes inspector if at all possible. To override the default flags +# that get passed to ${CC} (e.g. change -O to -O2), see Makefile.postamble. The +# variables below are *inputs* to the build process and distinct from the override +# settings done (less often) in the Makefile.postamble. +# +# OTHER_CFLAGS, LOCAL_CFLAGS: additional flags to pass to the compiler +# Note that $(OTHER_CFLAGS) and $(LOCAL_CFLAGS) are used for .h, ...c, .m, +# .cc, .cxx, .C, and .M files. There is no need to respecify the +# flags in OTHER_MFLAGS, etc. +# OTHER_MFLAGS, LOCAL_MFLAGS: additional flags for .m files +# OTHER_CCFLAGS, LOCAL_CCFLAGS: additional flags for .cc, .cxx, and ...C files +# OTHER_MMFLAGS, LOCAL_MMFLAGS: additional flags for .mm and .M files +# OTHER_PRECOMPFLAGS, LOCAL_PRECOMPFLAGS: additional flags used when +# precompiling header files +# OTHER_LDFLAGS, LOCAL_LDFLAGS: additional flags passed to ld and libtool +# OTHER_PSWFLAGS, LOCAL_PSWFLAGS: additional flags passed to pswrap +# OTHER_RPCFLAGS, LOCAL_RPCFLAGS: additional flags passed to rpcgen +# OTHER_YFLAGS, LOCAL_YFLAGS: additional flags passed to yacc +# OTHER_LFLAGS, LOCAL_LFLAGS: additional flags passed to lex + +# These variables provide hooks enabling you to add behavior at almost every +# stage of the make: +# +# BEFORE_PREBUILD: targets to build before installing headers for a subproject +# AFTER_PREBUILD: targets to build after installing headers for a subproject +# BEFORE_BUILD_RECURSION: targets to make before building subprojects +# BEFORE_BUILD: targets to make before a build, but after subprojects +# AFTER_BUILD: targets to make after a build +# +# BEFORE_INSTALL: targets to build before installing the product +# AFTER_INSTALL: targets to build after installing the product +# BEFORE_POSTINSTALL: targets to build before postinstalling every subproject +# AFTER_POSTINSTALL: targts to build after postinstalling every subproject +# +# BEFORE_INSTALLHDRS: targets to build before installing headers for a +# subproject +# AFTER_INSTALLHDRS: targets to build after installing headers for a subproject +# BEFORE_INSTALLSRC: targets to build before installing source for a subproject +# AFTER_INSTALLSRC: targets to build after installing source for a subproject +# +# BEFORE_DEPEND: targets to build before building dependencies for a +# subproject +# AFTER_DEPEND: targets to build after building dependencies for a +# subproject +# +# AUTOMATIC_DEPENDENCY_INFO: if YES, then the dependency file is +# updated every time the project is built. If NO, the dependency +# file is only built when the depend target is invoked. + +# Framework-related variables: +# FRAMEWORK_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the framework's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables + +# Library-related variables: +# PUBLIC_HEADER_DIR: Determines where public exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# PRIVATE_HEADER_DIR: Determines where private exported header files +# should be installed. Do not include $(DSTROOT) in this value -- +# it is prefixed automatically. +# LIBRARY_STYLE: This may be either STATIC or DYNAMIC, and determines +# whether the libraries produced are statically linked when they +# are used or if they are dynamically loadable. <> +# LIBRARY_DLL_INSTALLDIR: On Windows platforms, this variable indicates +# where to put the library's DLL. This variable defaults to +# $(INSTALLDIR)/../Executables +# +# INSTALL_AS_USER: owner of the intalled products (default root) +# INSTALL_AS_GROUP: group of the installed products (default wheel) +# INSTALL_PERMISSION: permissions of the installed product (default o+rX) +# +# OTHER_RECURSIVE_VARIABLES: The names of variables which you want to be +# passed on the command line to recursive invocations of make. Note that +# the values in OTHER_*FLAGS are inherited by subprojects automatically -- +# you do not have to (and shouldn't) add OTHER_*FLAGS to +# OTHER_RECURSIVE_VARIABLES. + +# Additional headers to export beyond those in the PB.project: +# OTHER_PUBLIC_HEADERS +# OTHER_PROJECT_HEADERS +# OTHER_PRIVATE_HEADERS + +# Additional files for the project's product: <> +# OTHER_RESOURCES: (non-localized) resources for this project +# OTHER_OFILES: relocatables to be linked into this project +# OTHER_LIBS: more libraries to link against +# OTHER_PRODUCT_DEPENDS: other dependencies of this project +# OTHER_SOURCEFILES: other source files maintained by .pre/postamble +# OTHER_GARBAGE: additional files to be removed by `make clean' + +# Set this to YES if you don't want a final libtool call for a library/framework. +# BUILD_OFILES_LIST_ONLY + +# To include a version string, project source must exist in a directory named +# $(NAME).%d[.%d][.%d] and the following line must be uncommented. +# OTHER_GENERATED_OFILES = $(VERS_OFILE) + +# This definition will suppress stripping of debug symbols when an executable +# is installed. By default it is YES. +# STRIP_ON_INSTALL = NO diff --git a/ypxfr.tproj/PB.project b/ypxfr.tproj/PB.project new file mode 100644 index 0000000..1371c2f --- /dev/null +++ b/ypxfr.tproj/PB.project @@ -0,0 +1,36 @@ +{ + DYNAMIC_CODE_GEN = YES; + FILESTABLE = { + FRAMEWORKS = (); + H_FILES = (ypdb.h, ypdef.h, yplib_host.h, yplog.h); + LIBRARYSEARCH = (); + OTHER_LIBS = (); + OTHER_LINKED = (ypdb.c, yplib_host.c, yplog.c, ypxfr.c, ypxfr_xdr.c); + OTHER_SOURCES = ( + Makefile.preamble, + Makefile, + Makefile.postamble, + ypxfr_1perday.sh, + ypxfr_1perhour.sh, + ypxfr_2perday.sh, + ypxfr.8 + ); + SUBPROJECTS = (); + }; + LANGUAGE = English; + LOCALIZABLE_FILES = {}; + MAKEFILEDIR = "$(MAKEFILEPATH)/pb_makefiles"; + NEXTSTEP_BUILDTOOL = /bin/gnumake; + NEXTSTEP_INSTALLDIR = /usr/sbin; + NEXTSTEP_JAVA_COMPILER = /usr/bin/javac; + NEXTSTEP_OBJCPLUS_COMPILER = /usr/bin/cc; + PDO_UNIX_BUILDTOOL = $NEXT_ROOT/Developer/bin/make; + PDO_UNIX_JAVA_COMPILER = "$(NEXTDEV_BIN)/javac"; + PDO_UNIX_OBJCPLUS_COMPILER = "$(NEXTDEV_BIN)/gcc"; + PROJECTNAME = ypxfr; + PROJECTTYPE = Tool; + PROJECTVERSION = 2.8; + WINDOWS_BUILDTOOL = $NEXT_ROOT/Developer/Executables/make; + WINDOWS_JAVA_COMPILER = "$(JDKBINDIR)/javac.exe"; + WINDOWS_OBJCPLUS_COMPILER = "$(DEVDIR)/gcc"; +} diff --git a/ypxfr.tproj/ypdb.c b/ypxfr.tproj/ypdb.c new file mode 100644 index 0000000..c9bd178 --- /dev/null +++ b/ypxfr.tproj/ypdb.c @@ -0,0 +1,297 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.c,v 1.5 1997/02/09 09:49:36 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +#include "ypdb.h" + +#ifdef YPDB_PATCH +extern DBM *__hash_open(); +#else +extern DBM *__bt_open(); +#endif + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + char path[MAXPATHLEN]; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + return ((DBM *)__hash_open(path, flags, mode, &info, 0)); +#else + BTREEINFO info; + char path[MAXPATHLEN]; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + snprintf(path, sizeof(path), "%s%s", file, YPDB_SUFFIX); + db = (DBM *)__bt_open(path, flags, mode, &info, 0); + return (db); +#endif +} + +/* + * Returns: + * *DBM on success + * NULL on failure + */ + +extern DBM * +ypdb_open_suf(file, flags, mode) + const char *file; + int flags, mode; +{ +#ifdef YPDB_PATCH + HASHINFO info; + + info.bsize = 4096; + info.ffactor = 40; + info.nelem = 1; + info.cachesize = NULL; + info.hash = NULL; + info.lorder = 0; + return ((DBM *)__hash_open(file, flags, mode, &info, 0)); +#else + BTREEINFO info; + DBM *db; + + info.flags = 0; + info.cachesize = 0; + info.maxkeypage = 0; + info.minkeypage = 0; + info.psize = 0; + info.compare = NULL; + info.prefix = NULL; + info.lorder = 0; + db = (DBM *)__bt_open(file, flags, mode, &info, 0); + return (db); +#endif +} + +extern void +ypdb_close(db) + DBM *db; +{ + (void)(db->close)(db); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_fetch(db, key) + DBM *db; + datum key; +{ + datum retval; + int status; + + status = (db->get)(db, (DBT *)&key, (DBT *)&retval, 0); + if (status) { + retval.dptr = NULL; + retval.dsize = 0; + } + return (retval); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_firstkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_nextkey(db) + DBM *db; +{ + int status; + datum retdata, retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + return (retkey); +} + +/* + * Returns: + * DATUM on success + * NULL on failure + */ + +extern datum +ypdb_setkey(db, key) + DBM *db; + datum key; +{ + int status; + datum retdata; +#ifdef YPDB_PATCH + datum retkey; + + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_FIRST); + if (status) + retkey.dptr = NULL; + while ((retkey.dptr != NULL) && + ((retkey.dsize != key.dsize) || + (strncmp(key.dptr,retkey.dptr,retkey.dsize) != 0))) { + status = (db->seq)(db, (DBT *)&retkey, (DBT *)&retdata, R_NEXT); + if (status) + retkey.dptr = NULL; + }; + return (retkey); +#else + status = (db->seq)(db, (DBT *)&key, (DBT *)&retdata, R_CURSOR); + if (status) + key.dptr = NULL; + return (key); +#endif +} + +/* + * Returns: + * 0 on success + * <0 failure + */ + +int +ypdb_delete(db, key) + DBM *db; + datum key; +{ + int status; + + status = (db->del)(db, (DBT *)&key, 0); + if (status) + return (-1); + else + return (0); +} + +/* + * Returns: + * 0 on success + * <0 failure + * 1 if YPDB_INSERT and entry exists + */ + +int +ypdb_store(db, key, content, flags) + DBM *db; + datum key, content; + int flags; +{ + return ((db->put)(db, (DBT *)&key, (DBT *)&content, + (flags == YPDB_INSERT) ? R_NOOVERWRITE : 0)); +} + diff --git a/ypxfr.tproj/ypdb.h b/ypxfr.tproj/ypdb.h new file mode 100644 index 0000000..9afbad5 --- /dev/null +++ b/ypxfr.tproj/ypdb.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdb.h,v 1.5 1997/02/09 09:49:37 maja Exp $ */ + +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * This code is derived from ndbm module of BSD4.4 db (hash) by + * Mats O Jansson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDB_H_ +#define _YPDB_H_ + +#ifndef _DB_H_ +#include +#endif + +#define YPDB_SUFFIX ".db" + +/* Flags to ypdb_store(). */ +#define YPDB_INSERT 0 +#define YPDB_REPLACE 1 + +#ifndef DATUM +typedef struct { + char *dptr; + int dsize; +} datum; +#define DATUM +#endif + +typedef DB DBM; + +__BEGIN_DECLS +void ypdb_close __P((DBM *)); +datum ypdb_fetch __P((DBM *, datum)); +datum ypdb_firstkey __P((DBM *)); +datum ypdb_nextkey __P((DBM *)); +datum ypdb_setkey __P((DBM *, datum)); +DBM *ypdb_open __P((const char *, int, int)); +DBM *ypdb_open_suf __P((const char *, int, int)); +int ypdb_store __P((DBM *, datum, datum, int)); +__END_DECLS + +#endif /* !_YPDB_H_ */ diff --git a/ypxfr.tproj/ypdef.h b/ypxfr.tproj/ypdef.h new file mode 100644 index 0000000..89970d7 --- /dev/null +++ b/ypxfr.tproj/ypdef.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypdef.h,v 1.6 1997/03/30 20:51:14 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPDEF_H_ +#define _YPDEF_H_ + +#define YP_DB_PATH "/var/yp" +#define YP_LAST_KEY "YP_LAST_MODIFIED" +#define YP_LAST_LEN (sizeof(YP_LAST_KEY)-1) +#define YP_INPUT_KEY "YP_INPUT_FILE" +#define YP_INPUT_LEN (sizeof(YP_INPUT_KEY)-1) +#define YP_OUTPUT_KEY "YP_OUTPUT_FILE" +#define YP_OUTPUT_LEN (sizeof(YP_OUTPUT_KEY)-1) +#define YP_MASTER_KEY "YP_MASTER_NAME" +#define YP_MASTER_LEN (sizeof(YP_MASTER_KEY)-1) +#define YP_DOMAIN_KEY "YP_DOMAIN_NAME" +#define YP_DOMAIN_LEN (sizeof(YP_DOMAIN_KEY)-1) +#define YP_INTERDOMAIN_KEY "YP_INTERDOMAIN" +#define YP_INTERDOMAIN_LEN (sizeof(YP_INTERDOMAIN_KEY)-1) +#define YP_SECURE_KEY "YP_SECURE" +#define YP_SECURE_LEN (sizeof(YP_SECURE_KEY)-1) + +#define MAX_LAST_LEN 10 +#define MAX_MASTER_LEN 255 +#define YP_HOSTNAME "hosts.byname" +#define YP_HOSTADDR "hosts.byaddr" + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define YPXFR_PROC "/usr/sbin/ypxfr" +#define YPPUSH_PROC "/usr/sbin/yppush" +#define YPSERV_PID_PATH "/var/run/ypserv.pid" +#define YP_SECURENET_FILE "/var/yp/securenet" + +#endif /* !_YPDEF_H_ */ diff --git a/ypxfr.tproj/yplib_host.c b/ypxfr.tproj/yplib_host.c new file mode 100644 index 0000000..70b914b --- /dev/null +++ b/ypxfr.tproj/yplib_host.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $ */ + +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char *rcsid = "$OpenBSD: yplib_host.c,v 1.7 1997/06/23 01:11:12 deraadt Exp $"; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern bool_t xdr_domainname(), xdr_ypbind_resp(); +extern bool_t xdr_ypreq_key(), xdr_ypresp_val(); +extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val(); +extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq(); +extern bool_t xdr_ypresp_master(); + +extern int (*ypresp_allfn)(); +extern void *ypresp_data; + +int _yplib_host_timeout = 10; + +CLIENT * +yp_bind_host(server,program,version,port,usetcp) +char *server; +u_long program,version; +u_short port; +int usetcp; +{ + struct sockaddr_in rsrv_sin; + int rsrv_sock; + struct hostent *h; + struct timeval tv; + static CLIENT *client; + + memset(&rsrv_sin, 0, sizeof rsrv_sin); + rsrv_sin.sin_len = sizeof rsrv_sin; + rsrv_sin.sin_family = AF_INET; + rsrv_sock = RPC_ANYSOCK; + if (port != 0) { + rsrv_sin.sin_port = htons(port); + } + + if ((*server >= '0') && (*server <= '9')) { + if(inet_aton(server,&rsrv_sin.sin_addr) == 0) { + fprintf(stderr, "inet_aton: invalid address %s.\n", + server); + exit(1); + } + } else { + h = gethostbyname(server); + if(h == NULL) { + fprintf(stderr, "gethostbyname: unknown host %s.\n", + server); + exit(1); + } + rsrv_sin.sin_addr.s_addr = *(u_int32_t *)h->h_addr; + } + + tv.tv_sec = 10; + tv.tv_usec = 0; + + if (usetcp) { + client = clnttcp_create(&rsrv_sin, program, version, + &rsrv_sock, 0, 0); + } else { + client = clntudp_create(&rsrv_sin, program, version, tv, + &rsrv_sock); + } + + if (client == NULL) { + fprintf(stderr, "clntudp_create: no contact with host %s.\n", + server); + exit(1); + } + + return(client); + +} + +CLIENT * +yp_bind_local(program,version) +u_long program,version; +{ + struct sockaddr_in rsrv_sin; + int rsrv_sock; + struct timeval tv; + static CLIENT *client; + + memset(&rsrv_sin, 0, sizeof rsrv_sin); + rsrv_sin.sin_len = sizeof rsrv_sin; + rsrv_sin.sin_family = AF_INET; + rsrv_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + rsrv_sock = RPC_ANYSOCK; + + tv.tv_sec = 10; + tv.tv_usec = 0; + + client = clntudp_create(&rsrv_sin, program, version, tv, &rsrv_sock); + if (client == NULL) { + fprintf(stderr,"clntudp_create: no contact with localhost.\n"); + exit(1); + } + + return(client); + +} + +int +yp_match_host(client, indomain, inmap, inkey, inkeylen, outval, outvallen) +CLIENT *client; +char *indomain; +char *inmap; +const char *inkey; +int inkeylen; +char **outval; +int *outvallen; +{ + struct ypresp_val yprv; + struct timeval tv; + struct ypreq_key yprk; + int r; + + *outval = NULL; + *outvallen = 0; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprk.domain = indomain; + yprk.map = inmap; + yprk.key.keydat_val = (char *)inkey; + yprk.key.keydat_len = inkeylen; + + memset(&yprv, 0, sizeof yprv); + + r = clnt_call(client, YPPROC_MATCH, + xdr_ypreq_key, &yprk, xdr_ypresp_val, &yprv, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_match_host: clnt_call"); + } + if( !(r=ypprot_err(yprv.stat)) ) { + *outvallen = yprv.val.valdat_len; + *outval = (char *)malloc(*outvallen+1); + memcpy(*outval, yprv.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + } + xdr_free(xdr_ypresp_val, (char *)&yprv); + return r; +} + +int +yp_first_host(client, indomain, inmap, outkey, outkeylen, outval, outvallen) +CLIENT *client; +char *indomain; +char *inmap; +char **outkey; +int *outkeylen; +char **outval; +int *outvallen; +{ + struct ypresp_key_val yprkv; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + + *outkey = *outval = NULL; + *outkeylen = *outvallen = 0; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + memset(&yprkv, 0, sizeof yprkv); + + r = clnt_call(client, YPPROC_FIRST, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_key_val, &yprkv, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_first_host: clnt_call"); + } + if( !(r=ypprot_err(yprkv.stat)) ) { + *outkeylen = yprkv.key.keydat_len; + *outkey = (char *)malloc(*outkeylen+1); + memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); + (*outkey)[*outkeylen] = '\0'; + *outvallen = yprkv.val.valdat_len; + *outval = (char *)malloc(*outvallen+1); + memcpy(*outval, yprkv.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + } + xdr_free(xdr_ypresp_key_val, (char *)&yprkv); + return r; +} + +int +yp_next_host(client, indomain, inmap, inkey, inkeylen, outkey, outkeylen, outval, outvallen) +CLIENT *client; +char *indomain; +char *inmap; +char *inkey; +int inkeylen; +char **outkey; +int *outkeylen; +char **outval; +int *outvallen; +{ + struct ypresp_key_val yprkv; + struct ypreq_key yprk; + struct timeval tv; + int r; + + *outkey = *outval = NULL; + *outkeylen = *outvallen = 0; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprk.domain = indomain; + yprk.map = inmap; + yprk.key.keydat_val = inkey; + yprk.key.keydat_len = inkeylen; + memset(&yprkv, 0, sizeof yprkv); + + r = clnt_call(client, YPPROC_NEXT, + xdr_ypreq_key, &yprk, xdr_ypresp_key_val, &yprkv, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_next_host: clnt_call"); + } + if( !(r=ypprot_err(yprkv.stat)) ) { + *outkeylen = yprkv.key.keydat_len; + *outkey = (char *)malloc(*outkeylen+1); + memcpy(*outkey, yprkv.key.keydat_val, *outkeylen); + (*outkey)[*outkeylen] = '\0'; + *outvallen = yprkv.val.valdat_len; + *outval = (char *)malloc(*outvallen+1); + memcpy(*outval, yprkv.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + } + xdr_free(xdr_ypresp_key_val, (char *)&yprkv); + return r; +} + +int +yp_all_host(client, indomain, inmap, incallback) +CLIENT *client; +char *indomain; +char *inmap; +struct ypall_callback *incallback; +{ + struct ypreq_nokey yprnk; + struct timeval tv; + u_long status; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + ypresp_allfn = incallback->foreach; + ypresp_data = (void *)incallback->data; + + (void) clnt_call(client, YPPROC_ALL, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_all_seq, &status, tv); + xdr_free(xdr_ypresp_all_seq, (char *)&status); /* not really needed... */ + + if(status != YP_FALSE) + return ypprot_err(status); + return 0; +} + +int +yp_order_host(client, indomain, inmap, outorder) +CLIENT *client; +char *indomain; +char *inmap; +u_int32_t *outorder; +{ + struct ypresp_order ypro; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + + memset(&ypro, 0, sizeof ypro); + + r = clnt_call(client, YPPROC_ORDER, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_order, &ypro, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_order_host: clnt_call"); + } + + *outorder = ypro.ordernum; + xdr_free(xdr_ypresp_order, (char *)&ypro); + return ypprot_err(ypro.stat); +} + +int +yp_master_host(client, indomain, inmap, outname) +CLIENT *client; +char *indomain; +char *inmap; +char **outname; +{ + struct ypresp_master yprm; + struct ypreq_nokey yprnk; + struct timeval tv; + int r; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + yprnk.domain = indomain; + yprnk.map = inmap; + + memset(&yprm, 0, sizeof yprm); + + r = clnt_call(client, YPPROC_MASTER, + xdr_ypreq_nokey, &yprnk, xdr_ypresp_master, &yprm, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_master: clnt_call"); + } + if( !(r=ypprot_err(yprm.stat)) ) { + *outname = (char *)strdup(yprm.peer); + } + xdr_free(xdr_ypresp_master, (char *)&yprm); + return r; +} + +int +yp_maplist_host(client, indomain, outmaplist) +CLIENT *client; +char *indomain; +struct ypmaplist **outmaplist; +{ + struct ypresp_maplist ypml; + struct timeval tv; + int r; + + tv.tv_sec = _yplib_host_timeout; + tv.tv_usec = 0; + + memset(&ypml, 0, sizeof ypml); + + r = clnt_call(client, YPPROC_MAPLIST, + xdr_domainname, &indomain, xdr_ypresp_maplist, &ypml, tv); + if (r != RPC_SUCCESS) { + clnt_perror(client, "yp_maplist: clnt_call"); + } + *outmaplist = ypml.maps; + /* NO: xdr_free(xdr_ypresp_maplist, &ypml);*/ + return ypprot_err(ypml.stat); +} + diff --git a/ypxfr.tproj/yplib_host.h b/ypxfr.tproj/yplib_host.h new file mode 100644 index 0000000..038fb68 --- /dev/null +++ b/ypxfr.tproj/yplib_host.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplib_host.h,v 1.4 1997/05/01 22:14:45 niklas Exp $ */ + +/* + * Copyright (c) 1992, 1993 Theo de Raadt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Theo de Raadt. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPLIB_HOST_H_ +#define _YPLIB_HOST_H_ + +int yp_match_host __P((CLIENT *client, char *indomain, char *inmap, + const char *inkey, int inkeylen, char **outval, + int *outvallen)); +int yp_first_host __P((CLIENT *client, char *indomain, char *inmap, + char **outkey, int *outkeylen, char **outval, + int *outvallen)); +int yp_next_host __P((CLIENT *client, char *indomain, char *inmap, + char *inkey, int inkeylen, char **outkey, + int *outkeylen, char **outval, int *outvallen)); +int yp_master_host __P((CLIENT *client, + char *indomain, char *inmap, char **outname)); +int yp_order_host __P((CLIENT *client, + char *indomain, char *inmap, u_int32_t *outorder)); +int yp_all_host __P((CLIENT *client, char *indomain, char *inmap, + struct ypall_callback *incallback)); +int yp_maplist_host __P((CLIENT *client, char *indomain, + struct ypmaplist **outmaplist)); +CLIENT *yp_bind_local __P((u_long program, u_long version)); +CLIENT *yp_bind_host __P((char *server, u_long program, u_long version, + u_short port, int usetcp)); + +#endif /* _YPLIB_HOST_H_ */ + diff --git a/ypxfr.tproj/yplog.c b/ypxfr.tproj/yplog.c new file mode 100644 index 0000000..3460c9a --- /dev/null +++ b/ypxfr.tproj/yplog.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplog.c,v 1.5 1997/08/09 22:44:04 maja Exp $ */ + +/* + * Copyright (c) 1996 Charles D. Cranor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * yplog.c: replacement yplog routines for + * Mats O Jansson's ypserv program, as added by + * Chuck Cranor. + */ + +#include +#include +#include +#include +#ifdef __STDC__ +#include +#else +#include +#endif +#include "yplog.h" + +static FILE *logfp = NULL; /* the log file */ + +/* + * yplog(): like a printf, but to the log file. does the flush + * and data for you. + */ + +void +#ifdef __STDC__ +yplog(const char *fmt, ...) +#else +yplog(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; + +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + vyplog(fmt, ap); + va_end(ap); +} + +/* + * vyplog() support routine for yplog() + */ + +void +vyplog(fmt, ap) + register const char *fmt; + va_list ap; +{ + time_t t; + + if (logfp == NULL) + return; + (void)time(&t); + fprintf(logfp,"%.15s ", ctime(&t) + 4); + vfprintf(logfp, fmt, ap); + fprintf(logfp,"\n"); + fflush(logfp); +} + +/* + * open log + */ + +void +ypopenlog() +{ + static char logfn[] = "/var/yp/ypserv.log"; + + if (access(logfn, W_OK) == -1) + return; + logfp = fopen("/var/yp/ypserv.log", "a"); + if (logfp == NULL) + return; + yplog("yplog opened"); +} + +/* + * close log + */ + +void +ypcloselog() +{ + if (logfp) { + yplog("yplog closed"); + fclose(logfp); + logfp = NULL; + } +} diff --git a/ypxfr.tproj/yplog.h b/ypxfr.tproj/yplog.h new file mode 100644 index 0000000..dd9d6fb --- /dev/null +++ b/ypxfr.tproj/yplog.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: yplog.h,v 1.3 1996/05/30 09:53:04 deraadt Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _YPLOG_H_ +#define _YPLOG_H_ + +__BEGIN_DECLS +void yplog __P((const char *, ...)); +void vyplog __P((const char *, _BSD_VA_LIST_)); +void ypopenlog __P((void)); +void ypcloselog __P((void)); +__END_DECLS + +#endif /* !_YPLOG_H_ */ diff --git a/ypxfr.tproj/ypxfr.8 b/ypxfr.tproj/ypxfr.8 new file mode 100644 index 0000000..5a78dad --- /dev/null +++ b/ypxfr.tproj/ypxfr.8 @@ -0,0 +1,92 @@ +.\" $OpenBSD: ypxfr.8,v 1.5 1997/04/20 10:08:35 maja Exp $ +.\" Copyright (c) 1994 Mats O Jansson +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by Mats O Jansson +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS +.\" OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +.\" DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $OpenBSD: ypxfr.8,v 1.5 1997/04/20 10:08:35 maja Exp $ +.\" +.Dd August 18, 1994 +.Dt YPXFR 8 +.Os +.Sh NAME +.Nm ypxfr +.Nd get a YP map from YP server +.Sh SYNOPSIS +.Nm ypxfr +.Op Fl bcf +.Op Fl d Ar domain +.Op Fl h Ar host +.Op Fl s Ar domain +.Op Fl C Ar tid prog ipadd port +.Ar mapname +.Sh DESCRIPTION +.Nm ypxfr +is the utiliy in YP that transfers maps to the local host. +.Pp +Since the YP master transfers a map when it has changed, an YP slave should +check for missed maps regulary. This can be done via an entry in +.Xr crontab 5 . +The scripts +.Ar ypxfr_1perhour , ypxfr_2perday +and +.Ar ypxfr_1perday +could be used for that. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl b +Preserve the entry in the database informing a YP server to use +DNS to get information about unknown hosts. This option will only have +effect on the two maps hosts.byname and hosts.byaddr. +.It Fl c +Don't send a "Clear current map" to local ypserv process. Useful if ypserv +isn't running localy to avoid timeout message. +.It Fl f +Force map transfer, even if version of master is older than local copy. +.It Fl d Ar domain +Don't use default domain, use the specifiyed domain. +.It Fl h Ar host +Get map from host insteed of the maps master host. +.It Fl s Ar domain +Specify a source domain other than the target domain. +.It Fl C Ar tid prog ipadd port +This option is only used by ypserv. This is to open communication with +an yppush on another host. +.El +.Sh FILES +.Bl -tag -width /usr/sbin/ypxfr_1perhour -compact +.It Pa /usr/sbin/ypxfr_1perhour +.It Pa /usr/sbin/ypxfr_2perday +.It Pa /usr/sbin/ypxfr_1perday +.El +.Sh SEE ALSO +.Xr yp 8 , +.Xr yppush 8 , +.Xr ypserv 8 +.Sh AUTHOR +Mats O Jansson diff --git a/ypxfr.tproj/ypxfr.c b/ypxfr.tproj/ypxfr.c new file mode 100644 index 0000000..faa88bf --- /dev/null +++ b/ypxfr.tproj/ypxfr.c @@ -0,0 +1,668 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypxfr.c,v 1.22 1997/07/30 12:07:02 maja Exp $ */ + +/* + * Copyright (c) 1994 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: ypxfr.c,v 1.22 1997/07/30 12:07:02 maja Exp $"; +#endif + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "yplib_host.h" +#include "yplog.h" +#include "ypdb.h" +#include "ypdef.h" + +extern char *__progname; /* from crt0.o */ +DBM *db; + +extern bool_t xdr_ypresp_all_seq(); + +extern int (*ypresp_allfn)(); +extern void *ypresp_data; + +static int +ypxfr_foreach(status,keystr,keylen,valstr,vallen,data) +int status,keylen,vallen; +char *keystr,*valstr,*data; +{ + datum key,val; + + if (status == YP_NOMORE) + return(0); + + keystr[keylen] = '\0'; + valstr[vallen] = '\0'; + + key.dptr = keystr; + key.dsize = strlen(keystr); + + val.dptr = valstr; + val.dsize = strlen(valstr); + + ypdb_store(db, key, val, YPDB_INSERT); + + return 0; +} + +int +get_local_ordernum(domain, map, lordernum) +char *domain; +char *map; +u_int32_t *lordernum; +{ + char map_path[MAXPATHLEN]; + char order_key[] = YP_LAST_KEY; + char order[MAX_LAST_LEN+1]; + struct stat finfo; + DBM *db; + datum k,v; + int status; + + /* This routine returns YPPUSH_SUCC or YPPUSH_NODOM */ + + status = YPPUSH_SUCC; + + snprintf(map_path, sizeof map_path, "%s/%s", YP_DB_PATH, domain); + if (!((stat(map_path, &finfo) == 0) && + ((finfo.st_mode & S_IFMT) == S_IFDIR))) { + fprintf(stderr, "%s: domain %s not found locally\n", + __progname, domain); + status = YPPUSH_NODOM; + } + + if(status > 0) { + snprintf(map_path, sizeof map_path, "%s/%s/%s%s", + YP_DB_PATH, domain, map, YPDB_SUFFIX); + if(!(stat(map_path, &finfo) == 0)) { + status = YPPUSH_NOMAP; + } + } + + if(status > 0) { + snprintf(map_path, sizeof map_path, "%s/%s/%s", + YP_DB_PATH, domain, map); + db = ypdb_open(map_path, O_RDONLY, 0444); + if(db == NULL) { + status = YPPUSH_DBM; + } + + } + + if(status > 0) { + k.dptr = (char *)&order_key; + k.dsize = YP_LAST_LEN; + + v = ypdb_fetch(db,k); + ypdb_close(db); + + if (v.dptr == NULL) { + *lordernum = 0; + } else { + strncpy(order, v.dptr, sizeof order-1); + order[sizeof order-1] = '\0'; + *lordernum = (u_int32_t)atol(order); + } + } + + if((status == YPPUSH_NOMAP) || (status == YPPUSH_DBM)) { + *lordernum = 0; + status = YPPUSH_SUCC; + } + + return(status); + +} + +int +get_remote_ordernum(client, domain, map, lordernum, rordernum) +CLIENT *client; +char *domain; +char *map; +u_int32_t lordernum; +u_int32_t *rordernum; +{ + int status; + + status = yp_order_host(client, domain, map, rordernum); + + if (status == 0) { + if(*rordernum <= lordernum) { + status = YPPUSH_AGE; + } else { + status = YPPUSH_SUCC; + } + } + + return status; +} + +void +get_map(client,domain,map,incallback) +CLIENT *client; +char *domain; +char *map; +struct ypall_callback *incallback; +{ + (void)yp_all_host(client, domain, map, incallback); + +} + +DBM * +create_db(domain,map,temp_map) +char *domain; +char *map; +char *temp_map; +{ + return ypdb_open_suf(temp_map, O_RDWR, 0444); +} + +int +install_db(domain,map,temp_map) +char *domain; +char *map; +char *temp_map; +{ + char db_name[MAXPATHLEN]; + + snprintf(db_name, sizeof db_name, "%s/%s/%s%s", + YP_DB_PATH, domain, map, YPDB_SUFFIX); + rename(temp_map, db_name); + + return YPPUSH_SUCC; +} + +int +add_order(db, ordernum) +DBM *db; +u_int32_t ordernum; +{ + char datestr[11]; + datum key,val; + char keystr[] = YP_LAST_KEY; + int status; + + sprintf(datestr, "%010u", ordernum); + + key.dptr = keystr; + key.dsize = strlen(keystr); + + val.dptr = datestr; + val.dsize = strlen(datestr); + + status = ypdb_store(db, key, val, YPDB_INSERT); + if(status >= 0) { + status = YPPUSH_SUCC; + } else { + status = YPPUSH_DBM; + } + return(status); +} + +int +add_master(client, domain, map, db) +CLIENT *client; +char *domain; +char *map; +DBM *db; +{ + char keystr[] = YP_MASTER_KEY; + char *master; + int status; + datum key,val; + + master = NULL; + + /* Get MASTER */ + + status = yp_master_host(client, domain, map, &master); + + if(master != NULL) { + key.dptr = keystr; + key.dsize = strlen(keystr); + + val.dptr = master; + val.dsize = strlen(master); + + status = ypdb_store(db, key, val, YPDB_INSERT); + if(status >= 0) { + status = YPPUSH_SUCC; + } else { + status = YPPUSH_DBM; + } + } + + return status; +} + +int +add_interdomain(client, domain, map, db) +CLIENT *client; +char *domain; +char *map; +DBM *db; +{ + char keystr[] = YP_INTERDOMAIN_KEY; + char *value; + int vallen; + int status; + datum k,v; + + /* Get INTERDOMAIN */ + + k.dptr = keystr; + k.dsize = strlen(keystr); + + status = yp_match_host(client, domain, map, + k.dptr, k.dsize, &value, &vallen); + + if(status == 0 && value) { + v.dptr = value; + v.dsize = vallen; + + if(v.dptr != NULL) { + status = ypdb_store(db,k,v,YPDB_INSERT); + if(status >= 0) { + status = YPPUSH_SUCC; + } else { + status = YPPUSH_DBM; + } + } + } + + return 1; +} + +int +add_secure(client, domain, map, db) +CLIENT *client; +char *domain; +char *map; +DBM *db; +{ + char keystr[] = YP_SECURE_KEY; + char *value; + int vallen; + int status; + datum k,v; + + /* Get SECURE */ + + k.dptr = keystr; + k.dsize = strlen(keystr); + + status = yp_match_host(client, domain, map, + k.dptr, k.dsize, &value, &vallen); + + if(status > 0) { + v.dptr = value; + v.dsize = vallen; + + if(v.dptr != NULL) { + status = ypdb_store(db,k,v,YPDB_INSERT); + if(status >= 0) { + status = YPPUSH_SUCC; + } else { + status = YPPUSH_DBM; + } + } + } + + return status; + +} + +int +send_clear(client) +CLIENT *client; +{ + struct timeval tv; + int r; + int status; + + status = YPPUSH_SUCC; + + tv.tv_sec = 10; + tv.tv_usec = 0; + + /* Send CLEAR */ + + r = clnt_call(client, YPPROC_CLEAR, + xdr_void, 0, xdr_void, 0, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yp_clear: clnt_call"); + } + + return status; + +} + +int +send_reply(client,status,tid) +CLIENT *client; +u_long status; +u_long tid; +{ + struct timeval tv; + struct ypresp_xfr resp; + int r; + + tv.tv_sec = 10; + tv.tv_usec = 0; + + resp.transid = tid; + resp.xfrstat = status; + + /* Send CLEAR */ + + r = clnt_call(client, 1, + xdr_ypresp_xfr, &resp, xdr_void, 0, tv); + if(r != RPC_SUCCESS) { + clnt_perror(client, "yppushresp_xdr: clnt_call"); + } + + return status; + +} + +int +main (argc,argv) +int argc; +char *argv[]; +{ + int usage = 0; + int cflag = 0; + int fflag = 0; + int Cflag = 0; + int ch; + extern char *optarg; + char *domain; + char *host = NULL; + char *srcdomain = NULL; + char *tid = NULL; + char *prog = NULL; + char *ipadd = NULL; + char *port = NULL; + char *map = NULL; + u_int32_t ordernum, new_ordernum; + struct ypall_callback callback; + CLIENT *client; + int status,xfr_status; + int srvport; + + status = YPPUSH_SUCC; + client = NULL; + + yp_get_default_domain(&domain); + + while ((ch = getopt(argc, argv, "cd:fh:s:C:")) != -1) + switch (ch) { + case 'c': + cflag++; + break; + case 'd': + if (strchr(optarg, '/')) /* Ha ha, we are not listening */ + break; + domain = optarg; + break; + case 'f': + fflag++; + break; + case 'h': + host = optarg; + break; + case 's': + if (strchr(optarg, '/')) /* Ha ha, we are not listening */ + break; + srcdomain = optarg; + break; + case 'C': + if (optind + 3 >= argc) { + usage++; + optind = argc; + break; + } + Cflag++; + tid = optarg; + prog = argv[optind++]; + ipadd = argv[optind++]; + port = argv[optind++]; + break; + default: + usage++; + break; + } + + if(optind + 1 != argc) { + usage++; + } else { + map = argv[optind]; + } + + if (usage) { + status = YPPUSH_BADARGS; + fprintf(stderr, "usage: %s %s %s\n", + "[-cf] [-d domain] [-h host] [-s domain]", + "[-C tid prog ipadd port] mapname\n", + __progname); + } + + if (status > 0) { + ypopenlog(); + + yplog("ypxfr: Arguments:"); + yplog("YP clear to local: %s", (cflag) ? "no" : "yes"); + yplog(" Force transfer: %s", (fflag) ? "yes" : "no"); + yplog(" domain: %s", domain); + yplog(" host: %s", host); + yplog(" source domain: %s", srcdomain); + yplog(" transid: %s", tid); + yplog(" prog: %s", prog); + yplog(" port: %s", port); + yplog(" ipadd: %s", ipadd); + yplog(" map: %s", map); + + if(fflag != 0) { + ordernum = 0; + } else { + status = get_local_ordernum(domain, map, &ordernum); + } + } + + if (status > 0) { + + yplog("Get Master"); + + if (host == NULL) { + if (srcdomain == NULL) { + status = yp_master(domain,map,&host); + } else { + status = yp_master(srcdomain,map,&host); + } + if(status == 0) { + status = YPPUSH_SUCC; + } else { + status = -status; + } + } + }; + + /* XXX this is raceable if portmap has holes! */ + if (status > 0) { + + yplog("Check for reserved port on host: %s", host); + + srvport = getrpcport(host,YPPROG,YPVERS,IPPROTO_TCP); + if (srvport >= IPPORT_RESERVED) + status = YPPUSH_REFUSED; + + } + + if (status > 0) { + + yplog("Connect host: %s", host); + + client = yp_bind_host(host,YPPROG,YPVERS,0,1); + + status = get_remote_ordernum(client, domain, map, + ordernum, &new_ordernum); + + } + + if (status == YPPUSH_SUCC) { + char tmpmapname[MAXPATHLEN]; + int fd; + + /* Create temporary db */ + snprintf(tmpmapname, sizeof tmpmapname, + "%s/%s/ypdbXXXXXXXXXX", YP_DB_PATH, domain); + fd = mkstemp(tmpmapname); + if (fd == -1) + status = YPPUSH_DBM; + else + close(fd); + + if (status > 0) { + db = create_db(domain,map,tmpmapname); + if(db == NULL) + status = YPPUSH_DBM; + } + + /* Add ORDER */ + if(status > 0) { + status = add_order(db, new_ordernum); + } + + /* Add MASTER */ + if(status > 0) { + status = add_master(client,domain,map,db); + } + + /* Add INTERDOMAIN */ + if(status > 0) { + status = add_interdomain(client,domain,map,db); + } + + /* Add SECURE */ + if(status > 0) { + status = add_secure(client,domain,map,db); + } + + if(status > 0) { + callback.foreach=ypxfr_foreach; + get_map(client,domain,map,&callback); + } + + /* Close db */ + if(db != NULL) { + ypdb_close(db); + } + + /* Rename db */ + if(status > 0) { + status = install_db(domain,map,tmpmapname); + } else { + unlink(tmpmapname); + status = YPPUSH_SUCC; + } + + } + + xfr_status = status; + + if(client != NULL) { + clnt_destroy(client); + } + + /* YP_CLEAR */ + + if(!cflag) { + client = yp_bind_local(YPPROG,YPVERS); + status = send_clear(client); + clnt_destroy(client); + } + + if(Cflag > 0) { + /* Send Response */ + client = yp_bind_host(ipadd, + atoi(prog), + 1, + atoi(port), + 0); + status = send_reply(client,xfr_status,atoi(tid)); + clnt_destroy(client); + } + + return(0); + +} + diff --git a/ypxfr.tproj/ypxfr_1perday.sh b/ypxfr.tproj/ypxfr_1perday.sh new file mode 100755 index 0000000..dab042c --- /dev/null +++ b/ypxfr.tproj/ypxfr_1perday.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# $OpenBSD: ypxfr_1perday.sh,v 1.1 1997/04/20 10:08:36 maja Exp $ +# +# ypxfr_1perday.sh - YP maps to be updated daily +# + +/usr/sbin/ypxfr group.byname +/usr/sbin/ypxfr group.bygid +/usr/sbin/ypxfr protocols.byname +/usr/sbin/ypxfr protocols.bynumber +/usr/sbin/ypxfr networks.byname +/usr/sbin/ypxfr networks.byaddr +/usr/sbin/ypxfr services.byname +/usr/sbin/ypxfr rpc.bynumber +/usr/sbin/ypxfr rpc.byname diff --git a/ypxfr.tproj/ypxfr_1perhour.sh b/ypxfr.tproj/ypxfr_1perhour.sh new file mode 100755 index 0000000..82f43a2 --- /dev/null +++ b/ypxfr.tproj/ypxfr_1perhour.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# $OpenBSD: ypxfr_1perhour.sh,v 1.1 1997/04/20 10:08:37 maja Exp $ +# +# ypxfr_1perhour.sh - YP maps to be updated every hour +# + +/usr/sbin/ypxfr passwd.byname +/usr/sbin/ypxfr passwd.byuid +/usr/sbin/ypxfr master.passwd.byname +/usr/sbin/ypxfr master.passwd.byuid +/usr/sbin/ypxfr netid.byname diff --git a/ypxfr.tproj/ypxfr_2perday.sh b/ypxfr.tproj/ypxfr_2perday.sh new file mode 100755 index 0000000..0905270 --- /dev/null +++ b/ypxfr.tproj/ypxfr_2perday.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# $OpenBSD: ypxfr_2perday.sh,v 1.1 1997/04/20 10:08:38 maja Exp $ +# +# ypxfr_2perday.sh - YP maps to be updated twice a day +# + +/usr/sbin/ypxfr hosts.byname +/usr/sbin/ypxfr hosts.byaddr +/usr/sbin/ypxfr ethers.byaddr +/usr/sbin/ypxfr ethers.byname diff --git a/ypxfr.tproj/ypxfr_xdr.c b/ypxfr.tproj/ypxfr_xdr.c new file mode 100644 index 0000000..460addf --- /dev/null +++ b/ypxfr.tproj/ypxfr_xdr.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights + * Reserved. This file contains Original Code and/or Modifications of + * Original Code as defined in and that are subject to the Apple Public + * Source License Version 1.0 (the 'License'). You may not use this file + * except in compliance with the License. Please obtain a copy of the + * License at http://www.apple.com/publicsource and read it before using + * this file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the + * License for the specific language governing rights and limitations + * under the License." + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* $OpenBSD: ypxfr_xdr.c,v 1.3 1996/06/26 21:26:41 maja Exp $ */ + +/* + * Copyright (c) 1995 Mats O Jansson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mats O Jansson + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef LINT +static char rcsid[] = "$OpenBSD: ypxfr_xdr.c,v 1.3 1996/06/26 21:26:41 maja Exp $"; +#endif + + + +#include +#include + +bool_t +xdr_ypxfrstat(xdrs, objp) + XDR *xdrs; + ypxfrstat *objp; +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +#ifdef notdef +bool_t +xdr_ypreq_xfr(xdrs, objp) + XDR *xdrs; + ypreq_xfr *objp; +{ + if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->prog)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->port)) { + return (FALSE); + } + return (TRUE); +} +#endif + +bool_t +xdr_ypresp_xfr(xdrs, objp) + XDR *xdrs; + ypresp_xfr *objp; +{ + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_ypxfrstat(xdrs, &objp->xfrstat)) { + return (FALSE); + } + return (TRUE); +} + + + + -- 2.45.2