ObjFW  Check-in [77d211a25a]

Overview
Comment:Add utils/ofatalkcfg

This is a utility to configure AppleTalk on a network interface.

For now, this is not built by default if AppleTalk sockets are
available, as it is still in an early state.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 77d211a25ab21f036005163a843dfd1d554a31000c369999c4598cd6cf202ab9
User & Date: js on 2023-04-11 19:20:31
Other Links: manifest | tags
Context
2023-04-12
06:54
Make utils/ofatalkcfg work on NetBSD check-in: e27b645562 user: js tags: trunk
2023-04-11
19:20
Add utils/ofatalkcfg check-in: 77d211a25a user: js tags: trunk
18:42
utils: Fix %c instead of %C for short options check-in: bb4026082a user: js tags: trunk
Changes

Modified .fossil-settings/clean-glob from [0ae1b8a1ac] to [af205be7e9].

47
48
49
50
51
52
53

54
55
56
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc

utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp







>



47
48
49
50
51
52
53
54
55
56
57
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofatalkcfg/ofatalkcfg
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp

Modified .fossil-settings/ignore-glob from [eed8ea3523] to [72d7550f75].

52
53
54
55
56
57
58

59
60
61
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc

utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp







>



52
53
54
55
56
57
58
59
60
61
62
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofatalkcfg/ofatalkcfg
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp

Modified .gitignore from [9fa51c850c] to [968910a4e3].

52
53
54
55
56
57
58

59
60
61
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc

utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp







>



52
53
54
55
56
57
58
59
60
61
62
tests/tests.arm9
tests/tests.nds
tests/tests.nro
tests/tests.rpx
utils/objfw-config
utils/objfw-new/objfw-new
utils/ofarc/ofarc
utils/ofatalkcfg/ofatalkcfg
utils/ofdns/ofdns
utils/ofhash/ofhash
utils/ofhttp/ofhttp

Modified utils/Makefile from [7fdfbaff17] to [92a1bc0dd9].

1
2
3
4

5
6
7
8
9
10
11
12
13
include ../extra.mk

SUBDIRS += ${OBJFW_NEW}	\
	   ${OFARC}	\

	   ${OFDNS}	\
	   ${OFHASH}	\
	   ${OFHTTP}

include ../buildsys.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile objfw-embed

|
|
|
>
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
include ../extra.mk
	
SUBDIRS += ${OBJFW_NEW}		\
	   ${OFARC}		\
	   ${OFATALKCFG}	\
	   ${OFDNS}		\
	   ${OFHASH}		\
	   ${OFHTTP}

include ../buildsys.mk

DISTCLEAN = objfw-config

install-extra: objfw-config objfw-compile objfw-embed

Added utils/ofatalkcfg/Makefile version [297ac97b13].









































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
include ../../extra.mk

PROG = ofatalkcfg${PROG_SUFFIX}
SRCS = OFATalkCfg.m

include ../../buildsys.mk

PACKAGE_NAME = ofatalkcfg

${PROG}: ${LIBOBJFW_DEP_LVL2} ${LIBOBJFWRT_DEP_LVL2}

CPPFLAGS += -I../../src							\
	    -I../../src/runtime						\
	    -I../../src/exceptions					\
	    -I../..
LIBS := -L../../src -lobjfw						\
	-L../../src/runtime -L../../src/runtime/linklib ${RUNTIME_LIBS}	\
	${LIBS}
LD = ${OBJC}
LDFLAGS += ${LDFLAGS_RPATH}

Added utils/ofatalkcfg/OFATalkCfg.m version [a520433515].













































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
/*
 * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
 *
 * All rights reserved.
 *
 * This file is part of ObjFW. It may be distributed under the terms of the
 * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
 * the packaging of this file.
 *
 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#ifdef HAVE_NET_IF_H
# include <net/if.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif

#import "OFApplication.h"
#import "OFArray.h"
#import "OFOptionsParser.h"
#import "OFSocket.h"
#import "OFStdIOStream.h"

#import "OFInvalidFormatException.h"

@interface OFATalkCfg: OFObject <OFApplicationDelegate>
@end

OF_APPLICATION_DELEGATE(OFATalkCfg)

static void
configureInterface(OFString *interface, uint16_t network, uint8_t node,
    uint8_t phase, uint16_t rangeStart, uint16_t rangeEnd)
{
	struct ifreq request = { 0 };
	struct sockaddr_at *sat;
	struct atalk_netrange *nr;
	int sock;

	if (interface.UTF8StringLength > IFNAMSIZ) {
		[OFStdErr writeFormat: @"%@: Interface name too long!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	strncpy(request.ifr_name, interface.UTF8String, IFNAMSIZ);
	sat = (struct sockaddr_at *)&request.ifr_addr;
	sat->sat_family = AF_APPLETALK;
	sat->sat_net = OFToBigEndian16(network);
	sat->sat_node = node;
	nr = (struct atalk_netrange *)(void *)sat->sat_zero;
	nr->nr_phase = phase;
	nr->nr_firstnet = OFToBigEndian16(rangeStart);
	nr->nr_lastnet = OFToBigEndian16(rangeEnd);

	if ((sock = socket(AF_APPLETALK, SOCK_DGRAM, 0)) < 0) {
		[OFStdErr writeFormat: @"%@: Failed to create socket: %@\n",
				       [OFApplication programName],
				       OFStrError(OFSocketErrNo())];
		[OFApplication terminateWithStatus: 1];
	}

	if (ioctl(sock, SIOCSIFADDR, &request) != 0) {
		[OFStdErr writeFormat: @"%@: Failed to set address: %@\n",
				       [OFApplication programName],
				       OFStrError(OFSocketErrNo())];
		[OFApplication terminateWithStatus: 1];
	}

	close(sock);
}

@implementation OFATalkCfg
- (void)applicationDidFinishLaunching: (OFNotification *)notification
{
	OFString *nodeString = nil, *networkString = nil, *phaseString = nil;
	OFString *rangeString = nil;
	const OFOptionsParserOption options[] = {
		{ '\0', @"network", 1, NULL, &networkString },
		{ '\0', @"node", 1, NULL, &nodeString },
		{ '\0', @"phase", 1, NULL, &phaseString },
		{ '\0', @"range", 1, NULL, &rangeString },
		{ '\0', nil, 0, NULL, NULL }
	};
	OFOptionsParser *optionsParser =
	    [OFOptionsParser parserWithOptions: options];
	OFUnichar option;
	unsigned long long node, network, phase, rangeStart, rangeEnd;
	OFArray OF_GENERIC(OFString *) *rangeArray;

	while ((option = [optionsParser nextOption]) != '\0') {
		switch (option) {
		case ':':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeFormat:
				    @"%@: Argument for option --%@ missing\n",
				    [OFApplication programName],
				    optionsParser.lastLongOption];
			else
				[OFStdErr writeFormat:
				    @"%@: Argument for option -%C missing\n",
				    [OFApplication programName],
				    optionsParser.lastOption];

			[OFApplication terminateWithStatus: 1];
			break;
		case '?':
			if (optionsParser.lastLongOption != nil)
				[OFStdErr writeFormat:
				    @"%@: Unknown option: --%@\n",
				    [OFApplication programName],
				    optionsParser.lastLongOption];
			else
				[OFStdErr writeFormat:
				    @"%@: Unknown option: -%C\n",
				    [OFApplication programName],
				    optionsParser.lastOption];

			[OFApplication terminateWithStatus: 1];
			break;
		}
	}

	if (optionsParser.remainingArguments.count == 0) {
		[OFStdErr writeFormat: @"%@: No interface specified!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	if (optionsParser.remainingArguments.count > 1) {
		[OFStdErr writeFormat: @"%@: More than one interface "
				       @"specified!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	if (networkString == nil) {
		[OFStdErr writeFormat: @"%@: --netwwork not specified!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	@try {
		network = [networkString unsignedLongLongValueWithBase: 0];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeFormat: @"%@: Invalid format for --network!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	if (network > UINT16_MAX) {
		[OFStdErr writeFormat: @"%@: --network out of range!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	if (nodeString == nil) {
		[OFStdErr writeFormat: @"%@: --node not specified!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	@try {
		node = [nodeString unsignedLongLongValueWithBase: 0];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeFormat: @"%@: Invalid format for --node!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	if (node > UINT8_MAX) {
		[OFStdErr writeFormat: @"%@: --node out of range!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	if (phaseString == nil) {
		[OFStdErr writeFormat: @"%@: --phase not specified!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	@try {
		phase = [phaseString unsignedLongLongValueWithBase: 0];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeFormat: @"%@: Invalid format for --phase!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	if (phase > 2) {
		[OFStdErr writeFormat: @"%@: --phase out of range!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	if (rangeString == nil) {
		[OFStdErr writeFormat: @"%@: --range not specified!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	rangeArray = [rangeString componentsSeparatedByString: @"-"];
	if (rangeArray.count != 2) {
		[OFStdErr writeFormat: @"%@: Invalid format for --range!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	@try {
		rangeStart = [[rangeArray objectAtIndex: 0]
		    unsignedLongLongValueWithBase: 0];
		rangeEnd = [[rangeArray objectAtIndex: 1]
		    unsignedLongLongValueWithBase: 0];
	} @catch (OFInvalidFormatException *e) {
		[OFStdErr writeFormat: @"%@: Invalid format for --range!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}
	if (rangeStart > UINT16_MAX || rangeEnd > UINT16_MAX) {
		[OFStdErr writeFormat: @"%@: --range out of range!\n",
				       [OFApplication programName]];
		[OFApplication terminateWithStatus: 1];
	}

	configureInterface(optionsParser.remainingArguments.firstObject,
	    (uint16_t)network, (uint8_t)node, (uint8_t)phase,
	    (uint16_t)rangeStart, (uint16_t)rangeEnd);

	[OFApplication terminate];
}
@end