blob: b33290e406da111c35f47d2e96f82b432476625e [file] [log] [blame]
Paul Stewart1c9a5662013-02-12 09:41:33 -08001// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// netfilter_queue_helper is a user-space process that allows unicast
6// replies to multicast requests. It does so by monitoring output
7// multicast packets on one NFQUEUE netlink iptables rule and collating
8// a list of input ports that are sending out multicast requests. It
9// uses these results to set policy on incoming UDP packets on a separate
10// NFQUEUE for replies addressed to that list of ports.
11//
12// Expected usage:
13// iptables -I OUTPUT 1 --proto udp
14// --destination <destination_multicast_address> --dport <dport>
15// -j NFQUEUE --queue-num <output_queue_number>
16// iptables -A INPUT --proto udp -j NFQUEUE --queue-num <input_queue_number>
17// netfilter_queue_helper --input-queue=<input_queue_number>
18// --output-queue=<output_queue_number>
19//
20// Note: in the above example, we preprend the OUTPUT rule so that it
21// runs even if lower rules would have accepted it, while the INPUT
22// rule is placed at the end of the rule list so any other firewall
23// rules that would have accepted the input packet for other reasons
24// will be evaluated first so we don't have to involve userspace for them.
25
26
27#include <string>
28
29#include <base/command_line.h>
30#include <base/logging.h>
31#include <base/string_number_conversions.h>
32#include <chromeos/syslog_logging.h>
33
34#include "shill/shims/netfilter_queue_processor.h"
35
36using std::string;
37
38namespace switches {
39
40static const char kHelp[] = "help";
41static const char kInputQueue[] = "input-queue";
42static const char kOutputQueue[] = "output-queue";
43
44// The help message shown if help flag is passed to the program.
45static const char kHelpMessage[] = "\n"
46 "Available Switches:\n"
47 " --help\n"
48 " Show this help message.\n"
49 " --input-queue=<input queue number>\n"
50 " Set the netfilter queue number for incoming UDP packets.\n"
51 " --output-queue=<output queue number>\n"
52 " Set the netfilter queue number for outgoing UDP packets for which\n"
53 " input replies will be enabled.\n";
54
55} // namespace switches
56
57bool GetIntegerOption(CommandLine *cl, const string &option, int *value) {
58 if (!cl->HasSwitch(option)) {
59 LOG(ERROR) << "Option " << option << " was not given.";
60 return false;
61 }
62 string option_string_value = cl->GetSwitchValueASCII(option);
63 int option_integer_value = -1;
64
65 if (!base::StringToInt(option_string_value, &option_integer_value)) {
66 LOG(ERROR) << "Unable to convert parameter \""
67 << option_string_value
68 << "\" passed as option "
69 << option
70 << " into an integer.";
71 return false;
72 }
73 *value = option_integer_value;
74 return true;
75}
76
77int main(int argc, char **argv)
78{
79 CommandLine::Init(argc, argv);
80 CommandLine *cl = CommandLine::ForCurrentProcess();
81
82 if (cl->HasSwitch(switches::kHelp)) {
83 LOG(INFO) << switches::kHelpMessage;
84 return 0;
85 }
86
87 int input_queue = -1;
88 if (!GetIntegerOption(cl, switches::kInputQueue, &input_queue) ||
89 input_queue < 0) {
90 LOG(ERROR) << "Unable to get mandatory input queue option.";
91 return 1;
92 }
93
94 int output_queue = -1;
95 if (!GetIntegerOption(cl, switches::kOutputQueue, &output_queue) ||
96 output_queue < 0) {
97 LOG(ERROR) << "Unable to get mandatory output queue option.";
98 return 1;
99 }
100
101 if (output_queue == input_queue) {
102 LOG(ERROR) << "Input and output queues must not be the same.";
103 return 1;
104 }
105
106 chromeos::InitLog(chromeos::kLogToSyslog | chromeos::kLogHeader);
107
108 shill::shims::NetfilterQueueProcessor processor(input_queue, output_queue);
109
110 if (!processor.Start()) {
111 LOG(ERROR) << "Failed to start netfilter processor.";
112 return 1;
113 }
114
115 processor.Run();
116
117 return 0;
118}