├── .gitignore ├── atp_internals.h ├── common.h ├── atp_input.h ├── nbp_lkup_async.h ├── tunnel.h ├── macip.h ├── util.h ├── util.c ├── Makefile ├── macipgw.8 ├── COPYRIGHT ├── README.md ├── atp_input.c ├── nbp_lkup_async.c ├── tunnel_linux.c ├── main.c └── macip.c /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | .vscode 3 | *.o 4 | .config* -------------------------------------------------------------------------------- /atp_internals.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1990,1991 Regents of The University of Michigan. 3 | * All Rights Reserved. 4 | * 5 | * Permission to use, copy, modify, and distribute this software and 6 | * its documentation for any purpose and without fee is hereby granted, 7 | * provided that the above copyright notice appears in all copies and 8 | * that both that copyright notice and this permission notice appear 9 | * in supporting documentation, and that the name of The University 10 | * of Michigan not be used in advertising or publicity pertaining to 11 | * distribution of the software without specific, written prior 12 | * permission. This software is supplied as is without expressed or 13 | * implied warranties of any kind. 14 | * 15 | * Research Systems Unix Group 16 | * The University of Michigan 17 | * c/o Mike Clark 18 | * 535 W. William Street 19 | * Ann Arbor, Michigan 20 | * +1-313-763-0525 21 | * netatalk@itd.umich.edu 22 | */ 23 | 24 | /* 25 | * masks for matching incoming packets 26 | */ 27 | #define ATP_FUNCANY ATP_TREQ | ATP_TRESP | ATP_TREL 28 | #define ATP_TIDANY 0xffff 29 | -------------------------------------------------------------------------------- /common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 1997 Stefan Bethke. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice unmodified, this list of conditions, and the following 9 | * disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | typedef void (*outputfunc_t)(char *buffer, int len); 28 | -------------------------------------------------------------------------------- /atp_input.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 1997 Stefan Bethke. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice unmodified, this list of conditions, and the following 9 | * disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | extern int atp_input(ATP ah, struct sockaddr_at *faddr, char *rbuf, int recvlen); 28 | -------------------------------------------------------------------------------- /nbp_lkup_async.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 1997 Stefan Bethke. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice unmodified, this list of conditions, and the following 9 | * disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | #include 27 | 28 | extern int nbp_lookup_req (int s, char *name, char *type, char *zone); 29 | extern struct nbpnve *nbp_parse_lkup_repl (char *buffer, int len); 30 | -------------------------------------------------------------------------------- /tunnel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 1997 Stefan Bethke. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice unmodified, this list of conditions, and the following 9 | * disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | extern int tunnel_open (uint32_t net, uint32_t mask, outputfunc_t o); 30 | extern void tunnel_close (void); 31 | extern void tunnel_input (void); 32 | extern void tunnel_output (char *buffer, int len); 33 | -------------------------------------------------------------------------------- /macip.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 1997 Stefan Bethke. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice unmodified, this list of conditions, and the following 9 | * disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | extern int macip_open (char *zone, uint32_t net, uint32_t mask, uint32_t ns, outputfunc_t o); 30 | extern void macip_close (void); 31 | extern void macip_idle (void); 32 | 33 | extern void macip_output (char *buffer, int len); 34 | extern void macip_input (void); 35 | 36 | -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) 1997 Stefan Bethke. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 1. Redistributions of source code must retain the above copyright 8 | * notice unmodified, this list of conditions, and the following 9 | * disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | * SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | extern int gDebug; 30 | 31 | #if defined(DEBUG) 32 | #define DEBUG_MACIP (0x0001) 33 | #define DEBUG_ROUTE (0x0010) 34 | #define DEBUG_TUNNEL (0x0100) 35 | #define DEBUG_DETAIL (0x1000) 36 | #else 37 | #define DEBUG_MACIP (0) 38 | #define DEBUG_ROUTE (0) 39 | #define DEBUG_TUNNEL (0) 40 | #define DEBUG_DETAIL (0) 41 | #endif 42 | 43 | extern char *iptoa (uint32_t ip); 44 | extern uint32_t atoip (char *s); 45 | 46 | 47 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Utitlity functions 3 | * 4 | * (c) 1997 Stefan Bethke. All rights reserved. 5 | * 6 | * Redistribution and use in source and binary forms, with or without 7 | * modification, are permitted provided that the following conditions 8 | * are met: 9 | * 1. Redistributions of source code must retain the above copyright 10 | * notice unmodified, this list of conditions, and the following 11 | * disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | * SUCH DAMAGE. 27 | */ 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | 35 | int gDebug; 36 | 37 | 38 | char *iptoa (uint32_t ip) { 39 | static char s[16]; 40 | 41 | sprintf (s, "%ld.%ld.%ld.%ld", 42 | (ip>>24) & 0xff, (ip>>16) & 0xff, 43 | (ip>> 8) & 0xff, ip & 0xff); 44 | return s; 45 | } 46 | 47 | 48 | uint32_t atoip (char *s) { 49 | uint32_t ip; 50 | 51 | ip = strtol (s, &s, 0); 52 | if (*s++ != '.' ) return 0; 53 | ip = (ip << 8) | strtol (s, &s, 0); 54 | if (*s++ != '.' ) return 0; 55 | ip = (ip << 8) | strtol (s, &s, 0); 56 | if (*s++ != '.' ) return 0; 57 | ip = (ip << 8) | strtol (s, &s, 0); 58 | if (*s != 0) return 0; 59 | return ip; 60 | } 61 | 62 | 63 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # AppleTalk MacIP Gateway 2 | # 3 | # Original work (c) 1997 Stefan Bethke. All rights reserved. 4 | # Modified work (c) 2015 Jason King. All rights reserved. 5 | # 6 | # Redistribution and use in source and binary forms, with or without 7 | # modification, are permitted provided that the following conditions 8 | # are met: 9 | # 1. Redistributions of source code must retain the above copyright 10 | # notice unmodified, this list of conditions, and the following 11 | # disclaimer. 12 | # 2. Redistributions in binary form must reproduce the above copyright 13 | # notice, this list of conditions and the following disclaimer in the 14 | # documentation and/or other materials provided with the distribution. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 | # SUCH DAMAGE. 27 | CC=gcc 28 | CFLAGS=-c -Wall -DDEBUG -g 29 | 30 | # Defaults are for a systemwide install of netatalk 3.x. 31 | # To compile against a local, already-built netatalk 2.x source tree, do: 32 | # export IFLAGS="-I/path/to/netatalk-2.x.y/include/ -I/path/to/netatalk-2.x.y/sys/" 33 | # export NO_LINK_ATALK=1 34 | # export LDFLAGS="/path/to/netatalk-2.x.y/libatalk/.libs/libatalk.a" 35 | 36 | IFLAGS+=-I/usr/local/include 37 | LDFLAGS+=-L/usr/local/lib 38 | ifndef NO_LINK_ATALK 39 | LDFLAGS+=-latalk 40 | endif 41 | 42 | SOURCES=atp_input.c macip.c main.c nbp_lkup_async.c tunnel_linux.c util.c 43 | OBJECTS=$(SOURCES:.c=.o) 44 | EXECUTABLE=macipgw 45 | DESTDIR = /usr/local/sbin 46 | 47 | all: $(SOURCES) $(EXECUTABLE) 48 | 49 | $(EXECUTABLE): $(OBJECTS) 50 | $(CC) $(IFLAGS) $(OBJECTS) -o $@ $(LDFLAGS) 51 | 52 | .c.o: 53 | $(CC) $(IFLAGS) $(CFLAGS) $< -o $@ 54 | 55 | clean: 56 | rm $(OBJECTS) $(EXECUTABLE) 57 | 58 | install: 59 | cp $(EXECUTABLE) $(DESTDIR) 60 | -------------------------------------------------------------------------------- /macipgw.8: -------------------------------------------------------------------------------- 1 | .TH "MACIPGW" 8 "July 23, 1997" "netatalk 1.4" 2 | .SH NAME 3 | macipgw \- MacIP Gateway Daemon 4 | .SH SYNOPSIS 5 | .B macipgw 6 | [\ \fB\-d\ debugclass\ \fR] 7 | [\ \fB\-n\ nameserver\ \fR] 8 | [\ \fB\-z\ zone\ \fR] 9 | [\ \fB\-V\ \fR] 10 | \fBnetwork netmask 11 | .SH DESCRIPTION 12 | .B macipgw 13 | provides IP connectivity for devices connected through an AppleTalk-only 14 | network, i.\ e. LocalTalk or Apple Remote Access (ARA). \fBmacipgw\fR is 15 | normally started out of \fB/etc/rc\fR. 16 | .LP 17 | MacIP (formerly known as KIP) is a protocol that allows the encapsulation of 18 | IP packets in AppleTalk packets. \fBmacipgw\fR registers itself as a MacIP 19 | gateway on the AppleTalk network and configures and brings up a tunnel 20 | interface (see \fBtun(4)\fR). It then forwards IP packets received from the 21 | AppleTalk network to the kernel through the tunnel interface. Likewise, IP 22 | packets received through the tunnel are forwarded to the AppleTalk device 23 | registered for the destination IP address. 24 | .LP 25 | Unlike other MacIP gateways, \fBmacipgw\fR needs its own IP (sub-)net to 26 | operate, and does not use proxy-ARP for the addresses registered. The 27 | gateway will always use the first address in the network for the local 28 | address, i.\ e. 192.168.1.1 for the network 192.168.1.0/24. 29 | .LP 30 | \fBmacipgw\fR will log operational messages through \fBsyslog(3)\fR under 31 | the facility \fBLOG_DAEMON\fR. 32 | .SH OPTIONS 33 | .TP 34 | .BI \-d " debugclass" 35 | Specifies that the daemon should not fork, and that a trace of all actions 36 | be written to \fBstdout\fR. See the source code for useful values of 37 | .IR debugclass . 38 | .TP 39 | .BI \-n " nameserver" 40 | Specifies the IP address of a DNS name server the AppleTalk devices 41 | connected through the gateway should use. 42 | .TP 43 | .BI \-z " zone" 44 | Specifies that \fBmacipgw\fR should register in \fIzone\fR instead of the 45 | default zone. 46 | .TP 47 | .B \-V 48 | Show version information and exit. 49 | .TP 50 | .B network 51 | Specifies the network number to use for the clients. 52 | .TP 53 | .B netmask 54 | Specifies the netmask for the network. 55 | .SH EXAMPLE 56 | \fB/usr/local/libexec/macipgw -n 192.168.1.1 -z "Remote Users" 192.168.1.0 57 | 255.255.255.0\fR 58 | 59 | Starts \fBmacipgw\fR, assigning the Class C network 192.168.1.0 for devices 60 | connected through the gateway, specifying that the system \fBmacipgw\fR is 61 | running on can be used as a name server, and that it should register in the 62 | zone \fIRemote Users\fR. 63 | .SH FILES 64 | .TP 20 65 | .B /usr/local/libexec/macipgw 66 | .SH SEE ALSO 67 | .BR tun(4) , 68 | .BR ip(4) , 69 | .BR atalkd(8) , 70 | .BR syslog(3) , 71 | .BR syslogd(8) 72 | .SH BUGS 73 | No information besides the log messages is available on which AppleTalk 74 | devices are using the gateway. 75 | .SH AUTHOR 76 | Stefan Bethke 77 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | AppleTalk MacIP Gateway 2 | 3 | $Id: COPYRIGHT,v 1.1.1.1 2001/10/28 15:01:48 stefanbethke Exp $ 4 | 5 | (c) 1997 Stefan Bethke. All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 1. Redistributions of source code must retain the above copyright 11 | notice unmodified, this list of conditions, and the following 12 | disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright 14 | notice, this list of conditions and the following disclaimer in the 15 | documentation and/or other materials provided with the distribution. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | SUCH DAMAGE. 28 | 29 | 30 | 31 | Copyright (c) 1990,1996 Regents of The University of Michigan. 32 | All Rights Reserved. 33 | 34 | Permission to use, copy, modify, and distribute this software and 35 | its documentation for any purpose and without fee is hereby granted, 36 | provided that the above copyright notice appears in all copies and 37 | that both that copyright notice and this permission notice appear 38 | in supporting documentation, and that the name of The University 39 | of Michigan not be used in advertising or publicity pertaining to 40 | distribution of the software without specific, written prior 41 | permission. This software is supplied as is without expressed or 42 | implied warranties of any kind. 43 | 44 | Copyright (c) 1988, 1992, 1993 45 | The Regents of the University of California. All rights reserved. 46 | 47 | Redistribution and use in source and binary forms, with or without 48 | modification, are permitted provided that the following conditions 49 | are met: 50 | 1. Redistributions of source code must retain the above copyright 51 | notice, this list of conditions and the following disclaimer. 52 | 2. Redistributions in binary form must reproduce the above copyright 53 | notice, this list of conditions and the following disclaimer in the 54 | documentation and/or other materials provided with the distribution. 55 | 3. All advertising materials mentioning features or use of this software 56 | must display the following acknowledgement: 57 | This product includes software developed by the University of 58 | California, Berkeley and its contributors. 59 | 4. Neither the name of the University nor the names of its contributors 60 | may be used to endorse or promote products derived from this software 61 | without specific prior written permission. 62 | 63 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 64 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 65 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 66 | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 67 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 68 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 69 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 70 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 71 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 72 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 73 | SUCH DAMAGE. 74 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### macipgw 2 | 3 | This is a Linux port of the FreeBSD MacIP gateway implementation originally written by Stefan Bethke. Stefan's original work is hosted on Sourceforge [here](http://macipgw.sourceforge.net). Most of the original AppleTalk code required little or no changes. The main work involved converting from FreeBSD tun interfaces to Linux tuntap interfaces. I left the original license intact and it is applied to all of the Linux-specific changes as well. 4 | 5 | The primary intent of this port was to have MacIP functionality on the Raspberry Pi so, while it may (and probably will) compile under other Linux variants, it has only been tested on Raspbian. 6 | 7 | Note: If you don't want to deal with compiling macipgw yourself, check out http://macip.net for a pre-configured VM that uses this code. 8 | 9 | ### Usage Examples 10 | 11 | The makefile has debugging enabled with the -DDEBUG switch, comment this out if you intend to run this without debugging. A typical command to run macipgw with debugging would look something like this: 12 | 13 | ./macipgw -d0x0111 -n 8.8.8.8 192.168.1.0 255.255.255.0 14 | 15 | The -d switch will specify that the daemon not fork and turn on debugging (0x0111). If you would like maximum debug detail including every packet, then use 0x1111. Debugging output can be useful for testing purposes or if you are having issues. The rest of the command tells the MacIP clients to use 8.8.8.8 for DNS, assigns 192.168.1.1 as the gateway address and issues MacIP client addresses in the range 192.168.1.2-254. Note that the network you use with this command MUST be unique from the network of any other interface. This is because macipgw sets up a separate MacIP network space and expects the host to route between that MacIP space and any other interface (e.g. eth0, wlan0, etc.) 16 | 17 | ### Routing 18 | 19 | Assuming that you already have AppleTalk enabled, the above command will be enough to get started with MacIP. However, by default Linux does not have IP forwarding enabled so if you want to route between your normal LAN network and the MacIP network, you need to enable IP forwarding: 20 | 21 | sysctl -w net.ipv4.ip_forward=1 22 | 23 | Once this has been enabled, you will be able to route between your MacIP network and any other network attached to the host. 24 | 25 | ### NAT 26 | 27 | The above may be enough for you if you have routing enabled throughout your LAN and can add routes to the MacIP network in the rest of your network devices, however, it is often convenient to just enable NAT on the outbound interface of the host using iptables. A typical iptables configuration to enable NAT on the wlan0 interface for the MacIP network outlined above would be: 28 | 29 | # Generated by iptables-save v1.4.14 on Thu Oct 15 22:54:35 2015 30 | *nat 31 | :PREROUTING ACCEPT [680:172998] 32 | :INPUT ACCEPT [122:18404] 33 | :OUTPUT ACCEPT [201:15275] 34 | :POSTROUTING ACCEPT [3:180] 35 | -A PREROUTING -s 192.168.1.0/24 -i tun0 36 | -A POSTROUTING -o wlan0 -j MASQUERADE 37 | COMMIT 38 | # Completed on Thu Oct 15 22:54:35 2015 39 | # Generated by iptables-save v1.4.14 on Thu Oct 15 22:54:35 2015 40 | *filter 41 | :INPUT ACCEPT [49565:4589890] 42 | :FORWARD ACCEPT [10606:4109172] 43 | :OUTPUT ACCEPT [32994:7213232] 44 | COMMIT 45 | # Completed on Thu Oct 15 22:54:35 2015 46 | Once this configuration is put in place, the host will NAT (well, PAT actually) any IP traffic originating from the MacIP network and being sent out the wlan0 interface. This would likely be a typical usage for macipgw on the Raspberry Pi. 47 | 48 | ### Kernel 49 | 50 | Your kernel must be configured with the CONFIG_IPDDP option *disabled* completely. It is not sufficient to compile it as a module -- in order to support the module, the kernel is modified to intercept all MacIP traffic, so userspace applications such as macipgw cannot handle it. 51 | 52 | ### Test Setup 53 | 54 | This was all developed and tested using a PowerBook 5300C, A2SERVER on the Raspberry Pi and an AsanteTalk bridge. The setup looks something like this: 55 | 56 | PowerBook 5300C ---- [LocalTalk] ---- AsanteTalk bridge ---- [Ethernet] ---- Raspberry Pi ---- [WiFi] ---- LAN 57 | 58 | It has also been tested with the following setup: 59 | 60 | PowerMac G3 All-in-One ---- [LocalTalk] ---- AsanteTalk bridge ---- [Ethernet] ---- Ubuntu x86_64, Linux kernel 4.2 ---- LAN 61 | 62 | ### Contact Info 63 | 64 | Email: jk1ng@yahoo.com 65 | -------------------------------------------------------------------------------- /atp_input.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Add an AT packet to ATPs input queue 3 | * 4 | * Original work (c) 1997 Stefan Bethke. All rights reserved. 5 | * Modified work (c) 2015 Jason King. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice unmodified, this list of conditions, and the following 12 | * disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #undef s_net 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "atp_internals.h" 43 | 44 | #ifdef EBUG 45 | #include 46 | #endif 47 | 48 | extern int at_addr_eq (struct sockaddr_at *paddr, struct sockaddr_at *saddr); 49 | extern int atp_free_buf (struct atpbuf *); 50 | extern struct atpbuf *atp_alloc_buf (void); 51 | 52 | /*#define EBUG 53 | */ 54 | 55 | int atp_input(ATP ah, struct sockaddr_at *faddr, char *rbuf, int recvlen) { 56 | struct atpbuf *pq, *cq; 57 | struct atphdr ahdr; 58 | u_short rfunc; 59 | u_short rtid; 60 | int i; 61 | struct atpbuf *inbuf; 62 | 63 | bcopy( rbuf + 1, (char *)&ahdr, sizeof( struct atphdr )); 64 | if ( recvlen >= ATP_HDRSIZE && *rbuf == DDPTYPE_ATP) { 65 | /* this is a valid ATP packet -- check for a match */ 66 | rfunc = ahdr.atphd_ctrlinfo & ATP_FUNCMASK; 67 | rtid = ahdr.atphd_tid; 68 | #ifdef EBUG 69 | printf( "<%d> got tid=%hu func=", getpid(), ntohs( rtid )); 70 | print_func( rfunc ); 71 | print_addr( " from", faddr ); 72 | putchar( '\n' ); 73 | bprint( rbuf, recvlen ); 74 | #endif 75 | if ( rfunc == ATP_TREL ) { 76 | /* remove response from sent list */ 77 | for ( pq = NULL, cq = ah->atph_sent; cq != NULL; 78 | pq = cq, cq = cq->atpbuf_next ) { 79 | if ( at_addr_eq( faddr, &cq->atpbuf_addr ) && 80 | cq->atpbuf_info.atpbuf_xo.atpxo_tid == ntohs( rtid )) 81 | break; 82 | } 83 | if ( cq != NULL ) { 84 | #ifdef EBUG 85 | printf( "<%d> releasing transaction %hu\n", getpid(), ntohs( rtid )); 86 | #endif 87 | if ( pq == NULL ) { 88 | ah->atph_sent = cq->atpbuf_next; 89 | } else { 90 | pq->atpbuf_next = cq->atpbuf_next; 91 | } 92 | for ( i = 0; i < 8; ++i ) { 93 | if ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] 94 | != NULL ) { 95 | atp_free_buf ( cq->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] ); 96 | } 97 | } 98 | atp_free_buf( cq ); 99 | } 100 | } else { 101 | /* add packet to incoming queue */ 102 | #ifdef EBUG 103 | printf( "<%d> queuing incoming...\n", getpid() ); 104 | #endif 105 | if (( inbuf = atp_alloc_buf()) == NULL ) { 106 | #ifdef EBUG 107 | printf( "<%d> can't alloc buffer\n", getpid() ); 108 | #endif 109 | return -1; 110 | } 111 | bcopy( (char *)faddr, (char *)&inbuf->atpbuf_addr, 112 | sizeof( struct sockaddr_at )); 113 | inbuf->atpbuf_next = ah->atph_queue; 114 | ah->atph_queue = inbuf; 115 | inbuf->atpbuf_dlen = recvlen; 116 | bcopy( (char *)rbuf, 117 | (char *)inbuf->atpbuf_info.atpbuf_data, recvlen ); 118 | } 119 | return 0; 120 | } 121 | 122 | return -1; /* invalid packet */ 123 | } 124 | 125 | 126 | -------------------------------------------------------------------------------- /nbp_lkup_async.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Asnychrounous NBP lookup 3 | * 4 | * Original work (c) 1997 Stefan Bethke. All rights reserved. 5 | * Modified work (c) 2015 Jason King. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice unmodified, this list of conditions, and the following 12 | * disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | * 29 | * Copyright (c) 1990,1996 Regents of The University of Michigan. 30 | * All Rights Reserved. 31 | * 32 | * Permission to use, copy, modify, and distribute this software and 33 | * its documentation for any purpose and without fee is hereby granted, 34 | * provided that the above copyright notice appears in all copies and 35 | * that both that copyright notice and this permission notice appear 36 | * in supporting documentation, and that the name of The University 37 | * of Michigan not be used in advertising or publicity pertaining to 38 | * distribution of the software without specific, written prior 39 | * permission. This software is supplied as is without expressed or 40 | * implied warranties of any kind. 41 | */ 42 | 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #include "nbp_lkup_async.h" 56 | 57 | extern int nbp_parse (char *, struct nbpnve *, int); 58 | 59 | static char *nbp_addstring (char *p, char *s) { 60 | int i; 61 | if (s) { 62 | if ((i = strlen (s)) > NBPSTRLEN ) 63 | i=31; 64 | *p++ = i; 65 | bcopy (s, p, i); 66 | p += i; 67 | } else { 68 | *p++ = 0; 69 | } 70 | return p; 71 | } 72 | 73 | static char *nbp_addtuple (char *p, struct sockaddr_at addr, 74 | char *name, char *type, char *zone) { 75 | struct nbptuple nt; 76 | 77 | nt.nt_net = addr.sat_addr.s_net; 78 | nt.nt_node = addr.sat_addr.s_node; 79 | nt.nt_port = addr.sat_port; 80 | bcopy( &nt, p, SZ_NBPTUPLE); 81 | p += SZ_NBPTUPLE; 82 | p = nbp_addstring (p, name); 83 | p = nbp_addstring (p, type); 84 | p = nbp_addstring (p, zone); 85 | return p; 86 | } 87 | 88 | int nbp_lookup_req (int s, char *name, char *type, char *zone) { 89 | static int rqid = 1; 90 | static int nbp_port = 0; 91 | struct sockaddr_at addr; 92 | unsigned int i; 93 | char buffer[500]; 94 | char *p = buffer; 95 | struct nbphdr nh; 96 | struct servent *se; 97 | 98 | i = sizeof (struct sockaddr_at); 99 | if (getsockname (s, (struct sockaddr *)&addr, &i) < 0 ) { 100 | return( -1 ); 101 | } 102 | 103 | *p++ = DDPTYPE_NBP; 104 | nh.nh_op = NBPOP_BRRQ; 105 | nh.nh_cnt = 1; 106 | nh.nh_id = rqid++; 107 | bcopy( &nh, p, SZ_NBPHDR ); 108 | p += SZ_NBPHDR; 109 | p = nbp_addtuple (p, addr, name, type, zone); 110 | 111 | bzero( &addr, sizeof( struct sockaddr_at )); 112 | addr.sat_family = AF_APPLETALK; 113 | addr.sat_addr.s_net = ATADDR_ANYNET; 114 | addr.sat_addr.s_node = ATADDR_ANYNODE; 115 | if ( nbp_port == 0 ) { 116 | if (( se = getservbyname( "nbp", "ddp" )) == NULL ) { 117 | nbp_port = 2; 118 | } else { 119 | nbp_port = ntohs( se->s_port ); 120 | } 121 | } 122 | addr.sat_port = nbp_port; 123 | 124 | #ifdef EBUG 125 | printf ("looking up '%s:%s@%s'\n", name, type, zone); 126 | #endif 127 | if ( sendto( s, buffer, p-buffer, 0, (struct sockaddr *)&addr, 128 | sizeof( struct sockaddr_at )) < 0 ) { 129 | return( -1 ); 130 | } 131 | return 0; 132 | } 133 | 134 | struct nbpnve *nbp_parse_lkup_repl (char *buffer, int len) { 135 | static char *lastbuffer = 0; 136 | static char *nexttuple = 0; 137 | static struct nbpnve nve; 138 | struct nbphdr *nh; 139 | int i; 140 | 141 | if (lastbuffer != buffer) { /* new packet */ 142 | lastbuffer = buffer; 143 | nexttuple = 0; 144 | if ( *buffer++ != DDPTYPE_NBP ) { 145 | return 0; 146 | } 147 | len--; 148 | 149 | nh = (struct nbphdr*)buffer; 150 | buffer += SZ_NBPHDR; 151 | if ( nh->nh_op != NBPOP_LKUPREPLY ) { 152 | return 0; 153 | } 154 | len -= SZ_NBPHDR; 155 | nexttuple = buffer; 156 | } else { 157 | len -= nexttuple - buffer; 158 | } 159 | i = nbp_parse (nexttuple, &nve, len); 160 | if (i >= 0) { 161 | nexttuple += len - i; 162 | #ifdef EBUG 163 | printf ("received nbp entry '%0.*s:%0.*s@%0.*s'\n", 164 | nve.nn_objlen, nve.nn_obj, 165 | nve.nn_typelen, nve.nn_type, 166 | nve.nn_zonelen, nve.nn_zone); 167 | #endif 168 | return &nve; 169 | } 170 | lastbuffer = 0; 171 | nexttuple = 0; 172 | return 0; 173 | } 174 | -------------------------------------------------------------------------------- /tunnel_linux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * AppleTalk MacIP Gateway 3 | * 4 | * Original work (c) 1997 Stefan Bethke. All rights reserved. 5 | * Modified work (c) 2015 Jason King. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice unmodified, this list of conditions, and the following 12 | * disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include "common.h" 48 | #include "util.h" 49 | #include "tunnel.h" 50 | 51 | struct tunnel { 52 | int dev; 53 | char name[32]; 54 | uint32_t net; 55 | uint32_t mask; 56 | }; 57 | 58 | static struct tunnel gTunnel; 59 | 60 | static outputfunc_t gOutput; 61 | 62 | static void set_sin (struct sockaddr *s, uint32_t ip) { 63 | struct sockaddr_in *sin = (struct sockaddr_in *)s; 64 | bzero (sin, sizeof (*sin)); 65 | sin->sin_family = AF_INET; 66 | sin->sin_addr.s_addr = htonl(ip); 67 | } 68 | 69 | static int tunnel_ifconfig (void) { 70 | int sk; 71 | struct ifreq ifrq; 72 | 73 | printf ("device = %s\n", gTunnel.name); 74 | 75 | sk = socket (PF_INET, SOCK_DGRAM, IPPROTO_IP); 76 | if (sk < 0) { 77 | if (gDebug & DEBUG_TUNNEL) 78 | perror ("tunnel_ifconfig: socket"); 79 | return -1; 80 | } 81 | 82 | bzero (&ifrq, sizeof (ifrq)); 83 | strncpy (ifrq.ifr_name, gTunnel.name, IFNAMSIZ); 84 | if (ioctl (sk, SIOCGIFFLAGS, &ifrq) < 0) { 85 | if (gDebug & DEBUG_TUNNEL) 86 | perror ("tunnel_ifconfig: SIOCGIFFLAGS"); 87 | close (sk); 88 | return -1; 89 | } 90 | 91 | ifrq.ifr_flags |= IFF_UP; 92 | if (ioctl (sk, SIOCSIFFLAGS, &ifrq) < 0) { 93 | if (gDebug & DEBUG_TUNNEL) 94 | perror ("tunnel_ifconfig: SIOCSIFFLAGS"); 95 | close (sk); 96 | return -1; 97 | } 98 | 99 | ifrq.ifr_mtu = 586; 100 | if (ioctl (sk, SIOCSIFMTU, &ifrq) < 0) { 101 | if (gDebug & DEBUG_TUNNEL) 102 | perror ("tunnel_ifconfig: SIOCSIFMTU"); 103 | close (sk); 104 | return -1; 105 | } 106 | 107 | set_sin (&ifrq.ifr_addr, gTunnel.net+1); 108 | if (ioctl (sk, SIOCSIFADDR, &ifrq) < 0) { 109 | if (gDebug & DEBUG_TUNNEL) 110 | perror ("tunnel_ifconfig: SIOCSIFADDR"); 111 | close (sk); 112 | return -1; 113 | } 114 | 115 | set_sin (&ifrq.ifr_addr, gTunnel.mask); 116 | if (ioctl (sk, SIOCSIFNETMASK, &ifrq) < 0) { 117 | if (gDebug & DEBUG_TUNNEL) 118 | perror ("tunnel_ifconfig: SIOCSIFNETMASK"); 119 | close (sk); 120 | return -1; 121 | } 122 | 123 | if (gDebug & DEBUG_TUNNEL) { 124 | printf ("tunnel_ifconfig: setting address %s -> ", iptoa(gTunnel.net+1)); 125 | printf ("%s netmask ", iptoa(gTunnel.net)); 126 | printf ("%s\n", iptoa(gTunnel.mask)); 127 | } 128 | 129 | close (sk); 130 | return 0; 131 | } 132 | 133 | static int tunnel_create(char *dev, int flags) { 134 | 135 | struct ifreq ifr; 136 | int fd; 137 | char *tundev = "/dev/net/tun"; 138 | 139 | if( (fd = open(tundev, O_RDWR)) < 0 ) { 140 | return fd; 141 | } 142 | 143 | memset(&ifr, 0, sizeof(ifr)); 144 | ifr.ifr_flags = flags; 145 | strncpy(ifr.ifr_name, dev, IFNAMSIZ); 146 | 147 | if (ioctl(fd, TUNSETIFF, (void *) &ifr) < 0 ) { 148 | if (gDebug & DEBUG_TUNNEL) 149 | perror ("tunnel_alloc: TUNSETIFF"); 150 | close(fd); 151 | return -1; 152 | } 153 | #if 0 154 | if (ioctl(fd, TUNSETPERSIST, 1) < 0) { 155 | if (gDebug & DEBUG_TUNNEL) 156 | perror ("tunnel_alloc: TUNSETPERSIST"); 157 | close(fd); 158 | return -1; 159 | } 160 | #endif 161 | strcpy(dev, ifr.ifr_name); 162 | 163 | return fd; 164 | } 165 | 166 | int tunnel_open (uint32_t net, uint32_t mask, outputfunc_t o) { 167 | int i; 168 | char s[32]; 169 | 170 | gTunnel.dev = 0; 171 | for (i=0; i<=9; i++) { 172 | sprintf (s, "tun%d", i); 173 | gTunnel.dev = tunnel_create (s, IFF_TUN | IFF_NO_PI); 174 | if (gTunnel.dev > 0) 175 | break; 176 | } 177 | 178 | if (gTunnel.dev < 0) { 179 | if (gDebug & DEBUG_TUNNEL) 180 | perror ("tunnel_open: open"); 181 | return -1; 182 | } 183 | 184 | strcpy (gTunnel.name, s); 185 | if (gDebug & DEBUG_TUNNEL) { 186 | printf ("tunnel_open: %s:%s opened.\n", s, gTunnel.name); 187 | } 188 | 189 | gTunnel.net = net; 190 | gTunnel.mask = mask; 191 | 192 | if (tunnel_ifconfig () < 0) { 193 | return -1; 194 | } 195 | 196 | gOutput = o; 197 | 198 | return gTunnel.dev; 199 | } 200 | 201 | void tunnel_close (void) { 202 | int sk; 203 | struct ifreq ifrq; 204 | 205 | sk = socket (PF_INET, SOCK_DGRAM, 0); 206 | if (sk < 0) { 207 | if (gDebug & DEBUG_TUNNEL) 208 | perror ("tunnel_close: socket"); 209 | return; 210 | } 211 | 212 | bzero (&ifrq, sizeof (ifrq)); 213 | strncpy (ifrq.ifr_name, gTunnel.name, IFNAMSIZ); 214 | 215 | if (ioctl (sk, SIOCGIFFLAGS, &ifrq) < 0) { 216 | if (gDebug & DEBUG_TUNNEL) 217 | perror ("tunnel_close: SIOCGIFFLAGS"); 218 | close (sk); 219 | return; 220 | } 221 | ifrq.ifr_flags &= ~IFF_UP; 222 | if (ioctl (sk, SIOCSIFFLAGS, &ifrq) < 0) { 223 | if (gDebug & DEBUG_TUNNEL) 224 | perror ("tunnel_close: SIOCSIFFLAGS"); 225 | close (sk); 226 | return; 227 | } 228 | 229 | close (gTunnel.dev); 230 | } 231 | 232 | 233 | void tunnel_input (void) { 234 | char buffer[600]; 235 | int i; 236 | 237 | i = read (gTunnel.dev, buffer, sizeof (buffer)); 238 | if (i < 0) { 239 | if (gDebug & DEBUG_TUNNEL) 240 | perror ("tunnel_input: read"); 241 | return; 242 | } 243 | if (gDebug & DEBUG_TUNNEL & DEBUG_DETAIL) 244 | printf ("read packet from tunnel.\n"); 245 | gOutput (buffer, i); 246 | } 247 | 248 | 249 | void tunnel_output (char *buffer, int len) { 250 | write (gTunnel.dev, buffer, len); 251 | if (gDebug & DEBUG_TUNNEL & DEBUG_DETAIL) 252 | printf ("sent packet into tunnel.\n"); 253 | } 254 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * AppleTalk MacIP Gateway 3 | * 4 | * Original work (c) 1997 Stefan Bethke. All rights reserved. 5 | * Modified work (c) 2015 Jason King. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice unmodified, this list of conditions, and the following 12 | * disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | #include 54 | 55 | #include "common.h" 56 | #include "macip.h" 57 | #include "tunnel.h" 58 | #include "util.h" 59 | 60 | static char *version = "macipgw 1.0\n" 61 | "Copyright (c) 1997 Stefan Bethke. All rights reserved.\n" 62 | "Copyright (c) 1988, 1992, 1993\n" 63 | "\tThe Regents of the University of California. All rights reserved.\n" 64 | "Copyright (c) 1990,1996 Regents of The University of Michigan.\n" 65 | "\tAll Rights Reserved.\n" 66 | "See the file COPYRIGHT for further information.\n"; 67 | 68 | int atsocket; 69 | int tundev; 70 | 71 | 72 | static void die (int n) { 73 | syslog (LOG_INFO, "going down on signal %d", n); 74 | if (gDebug) 75 | fprintf (stderr, "Stopping..."); 76 | macip_close (); 77 | tunnel_close (); 78 | if (gDebug) { 79 | fprintf (stderr, "stopped.\n"); 80 | fflush (stderr); 81 | } 82 | exit (n); 83 | } 84 | 85 | 86 | static void server(void) { 87 | fd_set fds; 88 | int maxfd = 0; 89 | struct timeval tv; 90 | int i; 91 | 92 | maxfd = atsocket; 93 | maxfd = MAX(maxfd, tundev); 94 | maxfd++; 95 | while (1) { 96 | FD_ZERO (&fds); 97 | FD_SET (atsocket, &fds); 98 | FD_SET (tundev, &fds); 99 | tv.tv_sec = 2; 100 | tv.tv_usec = 0; 101 | 102 | if (gDebug & DEBUG_DETAIL) { 103 | printf ("waiting for packet: "); 104 | fflush (stdout); 105 | } 106 | if ((i = select (maxfd, &fds, 0, 0, &tv)) > 0) { 107 | if (FD_ISSET (atsocket, &fds)) { 108 | if (gDebug & DEBUG_DETAIL) 109 | printf ("got AT packet.\n"); 110 | macip_input(); 111 | } else if (FD_ISSET (tundev, &fds)) { 112 | if (gDebug & DEBUG_DETAIL) 113 | printf ("got IP packet from tunnel.\n"); 114 | tunnel_input(); 115 | } 116 | } else { 117 | printf ("\r"); 118 | if (i == 0) { 119 | macip_idle (); 120 | } else { 121 | if (gDebug) 122 | perror ("select"); 123 | } 124 | } 125 | } 126 | } 127 | 128 | 129 | void disassociate (void) { 130 | int i, dt; 131 | 132 | switch ( fork()) { 133 | case 0 : 134 | dt = getdtablesize(); 135 | for ( i = 0; i < dt; i++ ) { 136 | (void)close( i ); 137 | } 138 | if (( i = open( "/dev/tty", O_RDWR )) >= 0 ) { 139 | (void)ioctl( i, TIOCNOTTY, 0 ); 140 | setpgrp(); 141 | (void)close( i ); 142 | } 143 | if (( i = open( "/", O_RDONLY )) >= 0 ) { 144 | dup2( i, 1 ); 145 | dup2( i, 2 ); 146 | } 147 | break; 148 | case -1 : 149 | perror ("fork"); 150 | die (EX_OSERR); 151 | default : 152 | exit (0); 153 | } 154 | } 155 | 156 | 157 | void usage (char *c) { 158 | if (c) 159 | fprintf (stderr, "%s\n", c); 160 | fprintf( stderr, "Usage:\tmacipgw [-d debug] [-z zone] [-n nameserver] [-u unprivileged-user] [-V]\n" 161 | "\t\tmacip-net macip-netmask\n"); 162 | exit (EX_USAGE); 163 | } 164 | 165 | struct passwd * get_user(const char *username) { 166 | struct passwd *pwd; 167 | pwd = getpwnam(username); 168 | if (pwd == NULL) { 169 | fprintf(stderr, "Unrecognized username: %s", username); 170 | exit (EX_USAGE); 171 | } 172 | return pwd; 173 | } 174 | 175 | 176 | int main(int argc, char *argv[]) { 177 | struct sigaction sv; 178 | uint32_t net=0, mask=0, ns=0; 179 | char *zone = "*"; 180 | int opt; 181 | 182 | struct passwd *pwd = NULL; 183 | uid_t user; 184 | gid_t group; 185 | 186 | gDebug = 0; 187 | 188 | while ((opt = getopt( argc, argv, "d:n:z:V:u:" )) != -1 ) { 189 | switch ( opt ) { 190 | case 'd': 191 | #if defined(DEBUG) 192 | gDebug = strtol (optarg, 0, 0); 193 | #else 194 | fprintf (stderr, "Please recompile macipgw with -DDEBUG to " 195 | "use debugging.\n"); 196 | exit (EX_USAGE); 197 | #endif 198 | break; 199 | 200 | case 'n': 201 | ns = atoip(optarg); 202 | break; 203 | 204 | case 'z': 205 | zone = optarg; 206 | break; 207 | case 'V': 208 | usage(version); 209 | break; 210 | case 'u': 211 | pwd = get_user(optarg); 212 | user = pwd->pw_uid; 213 | group = pwd->pw_gid; 214 | break; 215 | 216 | default: 217 | usage("unknown option."); 218 | } 219 | } 220 | argc -= optind; 221 | argv += optind; 222 | if (argc != 2) 223 | usage("wrong number of parameters."); 224 | net = atoip (argv[0]); 225 | mask = atoip (argv[1]); 226 | net &= mask; 227 | if ((net & mask) == 0) 228 | usage("invalid ip address."); 229 | 230 | openlog ("macipgw", LOG_PID | gDebug ? LOG_PERROR : 0, LOG_DAEMON); 231 | 232 | sv.sa_handler = die; 233 | sigemptyset(&sv.sa_mask); 234 | sv.sa_flags = 0; 235 | if (sigaction( SIGTERM, &sv, 0 ) < 0 ) { 236 | syslog( LOG_ERR, "sigaction: %m" ); 237 | exit (EX_OSERR); 238 | } 239 | if (sigaction( SIGQUIT, &sv, 0 ) < 0 ) { 240 | syslog( LOG_ERR, "sigaction: %m" ); 241 | exit (EX_OSERR); 242 | } 243 | if (sigaction( SIGINT, &sv, 0 ) < 0 ) { 244 | syslog( LOG_ERR, "sigaction: %m" ); 245 | exit (EX_OSERR); 246 | } 247 | 248 | if (!gDebug) 249 | disassociate(); 250 | 251 | 252 | tundev = tunnel_open (net, mask, macip_output); 253 | if (tundev < 0) { 254 | printf ("macipgw: could not open tunnel.\n"); 255 | die (EX_OSERR); 256 | } 257 | 258 | atsocket = macip_open (zone, net, mask, ns, tunnel_output); 259 | if (atsocket < 0) { 260 | printf ("macipgw: could not initialise MacIP\n"); 261 | die (EX_OSERR); 262 | } 263 | 264 | if (pwd) { 265 | if (setgid(user) == -1) { 266 | printf("macipgw: could not drop root privileges (group)\n"); 267 | die(EX_OSERR); 268 | } 269 | if (setuid(group) == -1) { 270 | printf("macipgw: could not drop root privileges (user)\n"); 271 | die(EX_OSERR); 272 | } 273 | } 274 | 275 | server(); 276 | 277 | return (0); 278 | } 279 | 280 | -------------------------------------------------------------------------------- /macip.c: -------------------------------------------------------------------------------- 1 | /* 2 | * AppleTalk MacIP Gateway 3 | * 4 | * Original work (c) 1997 Stefan Bethke. All rights reserved. 5 | * Modified work (c) 2015 Jason King. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice unmodified, this list of conditions, and the following 12 | * disclaimer. 13 | * 2. Redistributions in binary form must reproduce the above copyright 14 | * notice, this list of conditions and the following disclaimer in the 15 | * documentation and/or other materials provided with the distribution. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | #include 53 | #include 54 | #include 55 | #include 56 | 57 | #include "atp_input.h" 58 | #include "nbp_lkup_async.h" 59 | 60 | #include "common.h" 61 | #include "macip.h" 62 | #include "util.h" 63 | 64 | #define DDPTYPE_MACIP (22) 65 | #define MACIP_ASSIGN (1) 66 | #define MACIP_SERVER (3) 67 | #define MACIP_PORT (72) 68 | 69 | #define MACIP_MAXMTU (586) 70 | 71 | #define MACIP_NODETYPE "IPADDRESS" 72 | #define MACIP_GATETYPE "IPGATEWAY" 73 | 74 | #define MACIP_ATPRETRIES (5) 75 | #define MACIP_ATPWAIT (5) 76 | #define MACIP_NBPRETRIES (5) 77 | #define MACIP_NBPWAIT (5) 78 | 79 | #define ARPTIMEOUT (30) 80 | #define ARPRETRIES (10) 81 | /* ping every 30secs, give up after 5mins */ 82 | 83 | #define ASSIGN_FREE (0) 84 | #define ASSIGN_LEASED (1) 85 | #define ASSIGN_FIXED (2) 86 | 87 | struct macip_req_control { 88 | short mipr_version; 89 | short _mipr_pad1; 90 | uint32_t mipr_function; 91 | }; 92 | 93 | struct macip_req_data { 94 | uint32_t mipr_ipaddr; 95 | uint32_t mipr_nameserver; 96 | uint32_t mipr_broadcast; 97 | uint32_t _mipr_pad2; 98 | uint32_t mipr_subnet; 99 | }; 100 | 101 | struct macip_req { 102 | struct macip_req_control miprc; 103 | struct macip_req_data miprd; 104 | }; 105 | 106 | struct ipent { 107 | int assigned; 108 | long timo; 109 | int retr; 110 | struct sockaddr_at sat; 111 | }; 112 | 113 | struct macip_data { 114 | uint32_t net; 115 | uint32_t mask; 116 | uint32_t broadcast; 117 | uint32_t nameserver; 118 | uint32_t addr; 119 | int nipent; 120 | struct ipent *ipent; 121 | 122 | int sock; 123 | ATP atp; 124 | 125 | char name[32]; 126 | char type[32]; 127 | char zone[32]; 128 | }; 129 | 130 | #define IPADDR(e) (e - gMacip.ipent + gMacip.net + 1) 131 | 132 | #define MAXZONES 256 133 | 134 | struct zones { 135 | int n; 136 | char *z[MAXZONES]; 137 | }; 138 | 139 | static struct macip_data gMacip; 140 | static struct zones gZones; 141 | static outputfunc_t gOutput; 142 | 143 | static u_short 144 | cksum (char *buffer, int len) 145 | { 146 | u_short *b = (u_short *)buffer; 147 | uint32_t sum = 0; 148 | 149 | len /= 2; 150 | while (len--) { 151 | sum += *b++; 152 | } 153 | sum = (sum & 0xffff) + ((sum >> 16) & 0xffff); 154 | sum = sum > 65535 ? sum - 65535 : sum; 155 | return (~sum & 0xffff); 156 | } 157 | 158 | 159 | static void 160 | icmp_echo (uint32_t src, uint32_t dst) 161 | { 162 | char buffer[500]; 163 | struct ip *ip = (struct ip *)buffer; 164 | struct icmp *icmp = (struct icmp *)(buffer+20); 165 | 166 | bzero (buffer, sizeof (buffer)); 167 | ip->ip_v = IPVERSION; 168 | ip->ip_hl = 5; 169 | ip->ip_ttl = 255; 170 | ip->ip_src.s_addr = htonl (src); 171 | ip->ip_dst.s_addr = htonl (dst); 172 | ip->ip_id = 1; 173 | ip->ip_p = IPPROTO_ICMP; 174 | ip->ip_len = htons (20 + 8); 175 | ip->ip_sum = 0; 176 | ip->ip_sum = cksum((char *)ip, 20); 177 | icmp->icmp_type = ICMP_ECHO; 178 | icmp->icmp_code = 0; 179 | icmp->icmp_cksum = 0; 180 | icmp->icmp_cksum = cksum((char *)icmp, 8); 181 | 182 | macip_output (buffer, ntohs(ip->ip_len)); 183 | } 184 | 185 | 186 | 187 | static long now (void) { 188 | static struct timeval tv; 189 | 190 | gettimeofday (&tv, 0); 191 | return tv.tv_sec; 192 | } 193 | 194 | 195 | struct ipent *get_ipent(uint32_t ip) { 196 | return (ip-gMacip.net > 0 && ip-gMacip.net < gMacip.nipent) ? 197 | &gMacip.ipent[ip-gMacip.net-1] : 0; 198 | } 199 | 200 | /* 201 | * aquire a new ip address from the pool 202 | */ 203 | 204 | static uint32_t lease_ip () { 205 | int i; 206 | 207 | for (i=0; i < gMacip.nipent; i++) { 208 | if (gMacip.ipent[i].assigned == ASSIGN_FREE) { 209 | gMacip.ipent[i].assigned = ASSIGN_LEASED; 210 | bzero (&gMacip.ipent[i].sat, sizeof (struct sockaddr_at)); 211 | gMacip.ipent[i].retr = ARPRETRIES; 212 | gMacip.ipent[i].timo = ARPTIMEOUT; 213 | return gMacip.net + i + 1; 214 | } 215 | } 216 | return 0; 217 | } 218 | 219 | 220 | /* 221 | * find AT address for an IP address 222 | */ 223 | 224 | static int arp_lookup (struct sockaddr_at *sat, uint32_t ip) { 225 | int i; 226 | char s[32]; 227 | struct ipent *e = get_ipent (ip); 228 | 229 | if (e && e->assigned) { 230 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 231 | printf ("found arp entry: %s -> %d.%d\n", 232 | iptoa (ip), ntohs (e->sat.sat_addr.s_net), 233 | e->sat.sat_addr.s_node); 234 | bcopy (&e->sat, sat, sizeof (*sat)); 235 | return 1; 236 | } 237 | 238 | strcpy (s, iptoa (ip)); 239 | for (i=0; isat, sizeof (struct sockaddr_at)); 257 | e->timo = now()+ARPTIMEOUT; 258 | e->retr = ARPRETRIES; 259 | if (e->assigned == ASSIGN_FREE) 260 | e->assigned = ASSIGN_LEASED; 261 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 262 | printf ("arp_set: %s -> %d.%d\n", iptoa(ip), 263 | ntohs (sat->sat_addr.s_net), sat->sat_addr.s_node); 264 | } 265 | } 266 | 267 | /* 268 | * handle name lookup replies, add to arp table 269 | */ 270 | 271 | static void arp_input (struct sockaddr_at *sat, char *buffer, int len) { 272 | struct nbpnve *nve; 273 | char s[32]; 274 | uint32_t ip; 275 | 276 | while ((nve = nbp_parse_lkup_repl (buffer, len)) != NULL) { 277 | if (gDebug & DEBUG_MACIP) 278 | printf ("received nbp entry '%.*s:%.*s@%.*s'\n", 279 | nve->nn_objlen, nve->nn_obj, 280 | nve->nn_typelen, nve->nn_type, 281 | nve->nn_zonelen, nve->nn_zone); 282 | 283 | if (nve->nn_typelen != strlen(MACIP_NODETYPE) || 284 | strncasecmp (nve->nn_type, MACIP_NODETYPE, strlen (MACIP_NODETYPE)) != 0) { 285 | continue; 286 | } 287 | bcopy (nve->nn_obj, s, nve->nn_objlen); 288 | s[nve->nn_objlen] = 0; 289 | ip = atoip (s); 290 | if (ip == 0) 291 | continue; 292 | arp_set (ip, &nve->nn_sat); 293 | } 294 | /* send packets waiting */ 295 | } 296 | 297 | /* 298 | * handle incoming IP packet 299 | */ 300 | 301 | static void ip_input (struct sockaddr_at *sat, char *buffer, int len) { 302 | struct ip *p = (struct ip *)buffer; 303 | 304 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) { 305 | printf ("got IP packet from %d.%d\n", 306 | ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node); 307 | printf ("\tsource=%s, ", iptoa( ntohl(p->ip_src.s_addr) )); 308 | printf ("dest=%s\n", iptoa( ntohl(p->ip_dst.s_addr) )); 309 | } 310 | 311 | arp_set (ntohl(p->ip_src.s_addr), sat); 312 | 313 | gOutput (buffer, len); 314 | } 315 | 316 | /* 317 | * send IP packet through AT 318 | */ 319 | 320 | void macip_output (char *buffer, int len) { 321 | struct sockaddr_at sat; 322 | struct ip *ip = (struct ip *)buffer; 323 | char ob[MACIP_MAXMTU + 1]; 324 | 325 | if (len > MACIP_MAXMTU) { 326 | if (gDebug & DEBUG_MACIP) 327 | printf ("macip_output: packet too large, dropped.\n"); 328 | return; 329 | /* actually, we could fragment here, but this should never happen, 330 | as the MTU for the tunnel should be small enough. 331 | */ 332 | } 333 | if (arp_lookup (&sat, ntohl(ip->ip_dst.s_addr)) ) { 334 | bcopy (ip, ob+1, len); 335 | *ob = DDPTYPE_MACIP; 336 | len++; 337 | if (sendto (gMacip.sock, ob, len, 0, 338 | (struct sockaddr *)&sat, sizeof (sat)) <= 0) { 339 | if (gDebug & DEBUG_MACIP) 340 | perror ("macip_output: sendto"); 341 | } 342 | } else { 343 | /* XXX we could queue the packet here for delivery when the 344 | address has been looked up */ 345 | } 346 | } 347 | 348 | /* 349 | * handle configuration ATP request 350 | */ 351 | 352 | static void config_input (ATP atp, struct sockaddr_at *faddr, char *packet, int len) { 353 | struct atp_block atpb; 354 | struct sockaddr_at sat; 355 | struct iovec iov; 356 | char buffer[600]; 357 | struct macip_req *rq; 358 | int f; 359 | uint32_t ip; 360 | 361 | if (atp_input (atp, faddr, packet, len) < 0) { 362 | if (gDebug & DEBUG_MACIP) 363 | printf ("atp_input: packet rejected.\n"); 364 | return; 365 | } 366 | 367 | bzero (&sat, sizeof (sat)); 368 | sat.sat_family = AF_APPLETALK; 369 | sat.sat_addr.s_net = ATADDR_ANYNET; 370 | sat.sat_addr.s_node = ATADDR_ANYNODE; 371 | sat.sat_port = ATADDR_ANYPORT; 372 | 373 | if (atp_rsel (atp, &sat, ATP_TREQ) != ATP_TREQ ) { 374 | return; /* something other than a new request */ 375 | } 376 | 377 | atpb.atp_saddr = &sat; 378 | atpb.atp_rreqdata = buffer; 379 | atpb.atp_rreqdlen = sizeof(buffer); 380 | 381 | if (atp_rreq (atp, &atpb) < 0) { 382 | if (gDebug & DEBUG_MACIP) 383 | perror ("macip: config_input: atp_rreq"); 384 | return; 385 | } 386 | 387 | rq = (struct macip_req *)(atpb.atp_rreqdata); 388 | f = ntohl(rq->miprc.mipr_function); 389 | len = atpb.atp_rreqdlen; 390 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 391 | printf ("\nMacIP req: %d from %d.%d\n", f, 392 | ntohs(atpb.atp_saddr->sat_addr.s_net), 393 | atpb.atp_saddr->sat_addr.s_node); 394 | 395 | rq = (struct macip_req *)buffer; 396 | bzero (rq, sizeof (struct macip_req)); 397 | switch (f) { 398 | case MACIP_ASSIGN: 399 | rq->miprc.mipr_version = htonl(1); 400 | if ((ip = lease_ip ())) { 401 | rq->miprc.mipr_function = htonl(1); 402 | 403 | rq->miprd.mipr_ipaddr = htonl(ip); 404 | rq->miprd.mipr_nameserver = htonl(gMacip.nameserver); 405 | rq->miprd.mipr_broadcast = htonl(gMacip.broadcast); 406 | rq->miprd.mipr_subnet = htonl(gMacip.mask); 407 | len = sizeof (struct macip_req); 408 | arp_set (ip, &sat); 409 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 410 | printf ("assigned %s.\n", iptoa (ip)); 411 | } else { 412 | rq->miprc.mipr_function = htonl(0); 413 | len = sizeof (struct macip_req); 414 | } 415 | break; 416 | 417 | case MACIP_SERVER: 418 | rq->miprc.mipr_version = htonl(1); 419 | rq->miprc.mipr_function = htonl(3); 420 | len = sizeof (struct macip_req_control); 421 | break; 422 | 423 | default: 424 | if (gDebug & DEBUG_MACIP) 425 | printf ("macip_input: unknown request #%d received; ignored.\n", f); 426 | rq->miprc.mipr_version = htonl(1); 427 | rq->miprc.mipr_function = htonl(0); 428 | len = sizeof (struct macip_req_control); 429 | } 430 | iov.iov_base = buffer; 431 | iov.iov_len = len; 432 | 433 | atpb.atp_sresiov = &iov; 434 | atpb.atp_sresiovcnt = 1; 435 | if (atp_sresp (atp, &atpb) < 0 && gDebug & DEBUG_MACIP) { 436 | perror ("macip_input: atp_sresp"); 437 | } 438 | } 439 | 440 | /* 441 | * Handle incoming AT packet 442 | */ 443 | 444 | void macip_input (void) { 445 | struct sockaddr_at sat; 446 | char buffer[800]; 447 | int len; 448 | unsigned int flen; 449 | 450 | bzero (&sat, sizeof (sat)); 451 | sat.sat_family = AF_APPLETALK; 452 | sat.sat_addr.s_net = ATADDR_ANYNET; 453 | sat.sat_addr.s_node = ATADDR_ANYNODE; 454 | sat.sat_port = ATADDR_ANYPORT; 455 | 456 | flen = sizeof (struct sockaddr_at); 457 | if ((len=recvfrom (gMacip.sock, buffer, ATP_BUFSIZ, 458 | 0, (struct sockaddr *)&sat, &flen)) > 0) { 459 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 460 | printf ("macip_input: packet: DDP=%d, len=%d\n", *buffer, len); 461 | switch (*buffer) { /*DDPTYPE*/ 462 | case DDPTYPE_NBP: 463 | arp_input(&sat, buffer, len); 464 | break; 465 | case DDPTYPE_ATP: 466 | config_input(gMacip.atp, &sat, buffer, len); 467 | break; 468 | case DDPTYPE_MACIP: 469 | ip_input(&sat, buffer+1, len-1); 470 | break; 471 | } 472 | } else { 473 | perror ("recvfrom"); 474 | } 475 | } 476 | 477 | 478 | static int init_ip (uint32_t net, uint32_t mask, uint32_t nameserver) { 479 | bzero (&gMacip, sizeof(gMacip)); 480 | gMacip.net = net; 481 | gMacip.mask = mask; 482 | gMacip.nameserver = nameserver; 483 | gMacip.broadcast = net | ~mask; 484 | 485 | gMacip.nipent = (~mask) - 1; 486 | if ((gMacip.ipent = calloc (gMacip.nipent, sizeof(struct ipent))) == 0) { 487 | if (gDebug & DEBUG_MACIP) 488 | perror ("init_ip: calloc"); 489 | return -1; 490 | } 491 | 492 | gMacip.addr = net + 1; /* my address */ 493 | gMacip.ipent[0].assigned = ASSIGN_FIXED; 494 | 495 | if (gDebug & DEBUG_MACIP) { 496 | printf ("init_ip: network %s/", iptoa(gMacip.net)); 497 | printf ("%s, ", iptoa(gMacip.mask)); 498 | printf ("broadcast %s\n\t%d addresses availible\n", 499 | iptoa(gMacip.broadcast), gMacip.nipent - 1); 500 | printf ("\tmy ip=%s\n", iptoa(gMacip.net+1)); 501 | } 502 | 503 | return 0; 504 | } 505 | 506 | 507 | static void add_zones (short n, char *buf) { 508 | char s[32]; 509 | for ( ; n--; buf += (*buf) + 1 ) { 510 | if (gDebug & DEBUG_MACIP) 511 | printf( "add_zones: %.*s\n", *buf, buf+1 ); 512 | bcopy (buf+1, s, *buf); 513 | s[(int)*buf] = 0; 514 | if (gZones.n < MAXZONES) 515 | gZones.z[gZones.n++] = strdup (s); 516 | } 517 | } 518 | 519 | static int get_zones (void) { 520 | struct atp_handle *ah; 521 | struct atp_block atpb; 522 | struct sockaddr_at saddr; 523 | struct servent *se; 524 | char reqdata[4], buf[ ATP_MAXDATA ]; 525 | struct iovec iov; 526 | short temp, index = 0; 527 | int i; 528 | 529 | gZones.n = 0; 530 | 531 | reqdata[ 0 ] = ZIPOP_GETZONELIST; 532 | if (( ah = atp_open( 0, NULL )) == NULL ) { 533 | perror( "atp_open" ); 534 | return -1; 535 | } 536 | bzero( (char *) &saddr, sizeof( struct sockaddr_at )); 537 | saddr.sat_family = AF_APPLETALK; 538 | if (( se = getservbyname( "zip", "ddp" )) == NULL ) { 539 | fprintf( stderr, "Unknown service \"zip/ddp\".\n" ); 540 | return -1; 541 | } 542 | saddr.sat_port = ntohs( se->s_port ); 543 | saddr.sat_addr.s_net = ATADDR_ANYNET; 544 | saddr.sat_addr.s_node = ATADDR_ANYNODE; 545 | 546 | index = 1; 547 | reqdata[1] = 0; 548 | 549 | do { 550 | atpb.atp_saddr = &saddr; 551 | temp = htons( index ); 552 | bcopy( &temp, &reqdata[2], 2 ); 553 | atpb.atp_sreqdata = reqdata; 554 | atpb.atp_sreqdlen = 4; 555 | atpb.atp_sreqto = 2; 556 | atpb.atp_sreqtries = 5; 557 | 558 | /* send getzone request zones (or get my zone) 559 | */ 560 | if ( atp_sreq( ah, &atpb, 1, 0 ) < 0 ) { 561 | perror( "atp_sreq" ); 562 | return -1; 563 | } 564 | 565 | iov.iov_base = buf; 566 | iov.iov_len = ATP_MAXDATA; 567 | atpb.atp_rresiov = &iov; 568 | atpb.atp_rresiovcnt = 1; 569 | 570 | 571 | i = atp_rresp( ah, &atpb ); 572 | if (i < 0) { 573 | if (errno == ETIMEDOUT) { 574 | gZones.n = 1; 575 | gZones.z[0] = "*"; 576 | if (gDebug & DEBUG_MACIP) 577 | printf ("no zones on network\n"); 578 | return 0; 579 | } 580 | perror( "get_zones: atp_rresp" ); 581 | return -1; 582 | } 583 | 584 | bcopy( &((char *)iov.iov_base)[2], &temp, 2 ); 585 | temp = ntohs( temp ); 586 | 587 | add_zones( temp, iov.iov_base+4 ); 588 | 589 | index += temp; 590 | } while ( !((char *)iov.iov_base)[ 0 ] ); 591 | 592 | if ( atp_close( ah ) != 0 ) { 593 | perror( "atp_close" ); 594 | return -1; 595 | } 596 | return 0; 597 | } 598 | 599 | 600 | /* 601 | * time out old arp entries 602 | */ 603 | 604 | void macip_idle (void) { 605 | struct ipent *e; 606 | int i; 607 | long n = now(); 608 | 609 | for (i=gMacip.nipent, e=gMacip.ipent; i--; e++) { 610 | if ((e->assigned == ASSIGN_LEASED) && (e->timo < n)) { 611 | if (e->retr--) { 612 | icmp_echo (gMacip.addr, IPADDR(e)); 613 | e->timo = n + ARPTIMEOUT; 614 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 615 | printf ("macip_idle: sending probe to %s.\n", 616 | iptoa(IPADDR(e))); 617 | } else { 618 | e->assigned = ASSIGN_FREE; 619 | if (gDebug & DEBUG_MACIP & DEBUG_DETAIL) 620 | printf ("macip_idle: arp entry %s/%d.%d free'd.\n", 621 | iptoa(IPADDR(e)), ntohs(e->sat.sat_addr.s_net), 622 | e->sat.sat_addr.s_node); 623 | } 624 | } 625 | } 626 | } 627 | 628 | 629 | int 630 | macip_open (char *zone, uint32_t net, uint32_t mask, uint32_t ns, outputfunc_t o) { 631 | int i; 632 | 633 | if (init_ip (net, mask, ns)) { 634 | if (gDebug & DEBUG_MACIP) 635 | printf ("macip_open: init_ip failed.\n"); 636 | return -1; 637 | } 638 | 639 | for (i=0; i < MACIP_ATPRETRIES; i++) { 640 | if (i == MACIP_ATPRETRIES-1) { 641 | printf ("macip_open: too many retries\n"); 642 | return -1; 643 | } 644 | if ((gMacip.atp=atp_open(MACIP_PORT, NULL)) == NULL) { 645 | if (gDebug & DEBUG_MACIP) 646 | perror ("macip_open: atp_open"); 647 | printf ("macip_open: retrying in %d seconds\n", MACIP_ATPRETRIES); 648 | sleep (MACIP_ATPWAIT); 649 | } else 650 | break; 651 | } 652 | gMacip.sock = gMacip.atp->atph_socket; 653 | 654 | strcpy (gMacip.name, iptoa (gMacip.addr)); 655 | strcpy (gMacip.type, MACIP_GATETYPE); 656 | strcpy (gMacip.zone, zone); 657 | for (i=0; i < MACIP_NBPRETRIES; i++) { 658 | if (i == MACIP_NBPRETRIES-1) { 659 | printf ("macip_open: too many retries\n"); 660 | return -1; 661 | } 662 | if (gDebug & DEBUG_MACIP) { 663 | printf ("macip_open: registering %s:%s@%s...", 664 | gMacip.name, gMacip.type, gMacip.zone); 665 | fflush (stdout); 666 | } 667 | if (nbp_rgstr (atp_sockaddr (gMacip.atp), 668 | gMacip.name, 669 | gMacip.type, 670 | gMacip.zone) < 0) { 671 | if (gDebug & DEBUG_MACIP) 672 | perror ("failed"); 673 | printf ("macip_open: retrying in %d seconds\n", MACIP_NBPRETRIES); 674 | sleep (MACIP_NBPWAIT); 675 | } else 676 | break; 677 | } 678 | if (gDebug & DEBUG_MACIP) { 679 | printf ("done.\n"); 680 | fflush (stdout); 681 | } 682 | if (get_zones()) 683 | return -1; 684 | 685 | nbp_lookup_req (gMacip.sock, "=", "IPADDRESS", "*"); 686 | 687 | gOutput = o; 688 | 689 | return gMacip.sock; 690 | } 691 | 692 | 693 | void macip_close (void) { 694 | nbp_unrgstr( gMacip.name, gMacip.type, gMacip.zone, NULL); 695 | close (gMacip.sock); 696 | } 697 | --------------------------------------------------------------------------------