1 /* llcio -- use a connection over LLC to access a remote stream
3 * From: Rick van Rein <rick@openfortress.nl>
11 #include <net/if_arp.h>
12 #include <sys/socket.h>
13 #include <sys/select.h>
15 #include <linux/llc.h>
17 // TODO: What includes to use?
23 * LLC is a protocol that builds directly on top of the
24 * ethernet MAC layer. It can be connection-oriented or
25 * connectionless, the latter with or without acknowledge.
27 * Given that it does not run on top of IPv4 or IPv6, it
28 * will not route globally. This is a disadvantage for
29 * most uses, but it actually is an advantage to others.
30 * As an example use of LLC, think of console I/O with a
31 * networked device that works as soon as the networking
32 * hardware is setup -- specifically, there is no need
33 * for DHCP or any other protocol to obtain a higher level
34 * of existence. This is the kind of application that
35 * this tool was built for, so it is connection-oriented.
37 * Linux supports LLC, and that is the basis of this tool.
38 * A simple use of it would be to connect two instances
39 * of this program by telling each what the MAC address and
40 * SAP (service access point, a bit like ports in UDP/TCP)
41 * of the other end is -- and end up with a chat tool that
42 * runs over plain Ethernet.
44 * The same mechanism is a good replacement for serial
45 * consoles on embedded devices -- a network makes it
46 * easier to approach such a console.
50 void parsemac (unsigned char mac [6], char *mactxt) {
54 unsigned char *mactodo = mac;
56 val = strtol (here, &here, 16);
57 if ((val < 0x00) || (val > 0xff)) {
58 fprintf (stderr, "MAC address contains bad byte: 0x%lx\n", val);
62 if (*here++ != (todo? ':': '\0')) {
63 fprintf (stderr, "MAC address not properly formatted: %s\n", mactxt);
70 void parsesap (unsigned char *sap, char *saptxt) {
72 long sapval = strtol (saptxt, &endptr, 10);
73 if (*endptr != '\0') {
74 fprintf (stderr, "Failure parsing SAP: %s\n", saptxt);
77 if ((sapval < 0) || (sapval > 127)) {
78 fprintf (stderr, "SAP value must be 7 bit, not %s\n", saptxt);
81 if ((sapval & 0x03) || (sapval <= 0x03)) {
82 fprintf (stderr, "SAP value is a reserved value: %s\n", saptxt);
89 int main (int argc, char *argv []) {
90 /* Process parameters */
91 if ((argc != 3) && (argc != 5)) {
92 fprintf (stderr, "Usage: %s local_MAC local_SAP [remote_MAC remote_SAP]\n", argv [0]);
95 /* Acquire LLC socket */
96 int sox = socket (PF_LLC, SOCK_STREAM, 0);
98 perror ("Failed to acquire LLC socket");
101 /* Bind to a local address */
102 struct sockaddr_llc local, remot;
103 bzero (&local, sizeof (local));
104 bzero (&remot, sizeof (remot));
105 local.sllc_family = remot.sllc_family = PF_LLC;
106 local.sllc_arphrd = remot.sllc_arphrd = ARPHRD_ETHER;
107 parsemac ( local.sllc_mac, argv [1]);
108 parsesap (&local.sllc_sap, argv [2]);
109 if (bind (sox, (struct sockaddr *) &local, sizeof (local)) == -1) {
110 perror ("Failed to bind LLC address");
113 /* Choose between client and server role */
115 parsemac ( remot.sllc_mac, argv [3]);
116 parsesap (&remot.sllc_sap, argv [4]);
117 if (connect (sox, (struct sockaddr *) &remot, sizeof (remot)) == -1) {
118 perror ("Failed to connect to LLC peer");
122 if (listen (sox, 5) == -1) {
123 perror ("Failed to listen for LLC peers");
126 socklen_t remotlen = sizeof (remot);
127 sox = accept (sox, (struct sockaddr *) &remot, &remotlen);
129 perror ("Failed to accept LLC");
133 printf ("Connected\n");
139 FD_SET (sox, &inout);
140 if (select (sox + 1, &inout, NULL, NULL, NULL) == -1) {
141 perror ("Failed while waiting for input");
147 if (FD_ISSET (0, &inout)) {
148 buflen = read (0, buf, 80);
150 write (sox, buf, buflen);
154 perror ("Failed to read from stdin");
159 if (FD_ISSET (sox, &inout)) {
160 buflen = read (sox, buf, 80);
162 write (1, buf, buflen);
166 perror ("Failed to read LLC data");