/* plum-2_33_2 用、複数のNICを持つ環境のためのパッチ 設定ファイルの変更 ----------------------- plum.bind_src: juggler.jp:0 IRCサーバに接続する際にソケットのソースアドレスを指定する。 アドレスとポートの組を1つだけ書ける。複数の指定には対応していない。 ポート番号にはたいていの場合0を指定することになるだろう。 複数のポート番号をカンマで区切るとランダムに選ばれる。 アドレスに0を指定するとデフォルトのネットワークインタフェースを選択することになるかもしれない。 plum.client: * juggler.jp:4567 changeme 空白で区切った引数が3つある場合は次のように解釈する。 client_mask listen_host:listen_port password listen_hostはIRCクライアントからの接続を待つアドレスまたはホスト名を指定する。 *と書くと任意のアドレスをlistenする。 制限: ポート番号ごとに1種類のアドレス(*を含む)しか指定できない。 同じポートと異なるアドレスの組み合わせは正常に動作しない。 履歴 ------------------- 03/03/16(日) 20:02:44 tateisu@smilemark.com とりあえず書いてみた。一応動いているようだ パッチ本体 ----------------------- */ *** plum Wed Mar 24 23:38:18 1999 --- plum2-bindsrc Sun Mar 16 20:03:45 2003 *************** *** 1059,1066 **** } sub 'connect { ! local($host, $port) = @_; local($serverno, $socket, $ip, @addr, $name); if ($host =~ /^\d+$/) { $ip = $host; } elsif ($host =~ /^[\d\.]+$/) { --- 1059,1085 ---- } sub 'connect { ! local($host, $port,$bind_hostport) = @_; local($serverno, $socket, $ip, @addr, $name); + local($bind_name,$bhost,$bport,@bport); + undef $bind_name; + if(defined $bind_hostport){ + ($bhost,$bport)=split/:/,$bind_hostport; + @bport = split/,/,($bport||'0'); + $bport = $bport[rand @bport]; + if(length $bhost){ + if ($bhost =~ /^\d+$/) { + $ip = $bhost; + } elsif ($bhost =~ /^[\d\.]+$/) { + $ip = unpack('N', pack('C4',split(/\./, $bhost), 0, 0, 0)); + } else { + $ip = unpack('N', (gethostbyname($bhost))[4] ); + } + return 0 unless $ip; + $bind_name = pack($SOCKADDR, $AF_INET, $bport, $ip); + undef $ip; + } + } if ($host =~ /^\d+$/) { $ip = $host; } elsif ($host =~ /^[\d\.]+$/) { *************** *** 1070,1078 **** $ip = unpack('N', (gethostbyname($host))[4] || "\0\0\0\0"); } return 0 unless $ip; $socket = '\'S' . ++$handle; socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0; ! $name = pack($SOCKADDR, $AF_INET, $port, $ip); connect($socket, $name) || return 0; binmode($socket); $serverno = fileno($socket); --- 1089,1101 ---- $ip = unpack('N', (gethostbyname($host))[4] || "\0\0\0\0"); } return 0 unless $ip; + $name = pack($SOCKADDR, $AF_INET, $port, $ip); + $socket = '\'S' . ++$handle; socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0; ! if( defined $bind_name ){ ! bind($socket,$bind_name) || warn "bind_src $bhost($ip) port $bport $!\n"; ! } connect($socket, $name) || return 0; binmode($socket); $serverno = fileno($socket); *************** *** 1084,1097 **** } sub 'listen { ! local($port, $count) = @_; ! local($listenno, $socket, $name); $socket = '\'L' . ++$handle; socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0; if (defined($SOL_SOCKET) && defined($SO_REUSEADDR)) { setsockopt($socket, $SOL_SOCKET, $SO_REUSEADDR, pack('l', 1)); } ! $name = pack($SOCKADDR, $AF_INET, $port, unpack('N', $INADDR_ANY)); bind($socket, $name) || return 0; listen($socket, $count || $SOMAXCONN) || return 0; $listenno = fileno($socket); --- 1107,1132 ---- } sub 'listen { ! local($port, $count,$listen_host) = @_; ! local($listenno, $socket, $name,$addr); $socket = '\'L' . ++$handle; socket($socket, $PF_INET, $SOCK_STREAM, $PROTO) || return 0; if (defined($SOL_SOCKET) && defined($SO_REUSEADDR)) { setsockopt($socket, $SOL_SOCKET, $SO_REUSEADDR, pack('l', 1)); } ! if(defined $listen_host and $listen_host ne '*' ){ ! if ($listen_host =~ /^\d+$/) { ! $addr = $listen_host; ! } elsif ($listen_host =~ /^[\d\.]+$/) { ! $addr = unpack('N', pack('C4', split(/\./, $listen_host), 0, 0, 0)); ! } else { ! $addr=(gethostbyname($listen_host))[4] || return 0; ! $addr = unpack('N', $addr); ! } ! }else{ ! $addr = unpack('N', $INADDR_ANY); ! } ! $name = pack($SOCKADDR, $AF_INET, $port, $addr); bind($socket, $name) || return 0; listen($socket, $count || $SOMAXCONN) || return 0; $listenno = fileno($socket); *************** *** 1146,1152 **** ($host, $pass) = (split(/\s+/, $server), ''); ($name, $list) = split(/\:/, $host); @port = split(/\,/, $list || ''); ! $serverno = &'connect($name, $port[rand(@port)] || $IRCPORT); next unless $serverno; $'serverlist = &'add($'serverlist, $serverno); $'avail[$serverno] = 0; --- 1181,1187 ---- ($host, $pass) = (split(/\s+/, $server), ''); ($name, $list) = split(/\:/, $host); @port = split(/\,/, $list || ''); ! $serverno = &'connect($name,($port[rand(@port)] || $IRCPORT),&'property($userno, 'bind_src')); next unless $serverno; $'serverlist = &'add($'serverlist, $serverno); $'avail[$serverno] = 0; *************** *** 1182,1199 **** sub c_listen { local($userno) = @_; ! local($listenno, $name, $port, $i, $uselist); ! foreach $port (&get_port($userno)) { ! $port = $IRCPORT unless $port; next if &'exist($portlist, $port); ! $listenno = &'listen($port, $SOMAXCONN); next unless $listenno; $'listenlist = &'add($'listenlist, $listenno); $portlist = &'add($portlist, $port); } for ($i = 0; $i < @'username; $i++) { ! foreach $port (&get_port($i)) { ! $uselist = &'add($uselist, $port || $IRCPORT); } } foreach $lno (&'array($'listenlist)) { --- 1217,1235 ---- sub c_listen { local($userno) = @_; ! local($listenno, $name, $port, $i, $uselist,$hp,$host); ! foreach $hp(&get_port($userno) ){ ! ($host,$port)=split/:/,$hp; next if &'exist($portlist, $port); ! $listenno = &'listen($port, $SOMAXCONN,$host); next unless $listenno; $'listenlist = &'add($'listenlist, $listenno); $portlist = &'add($portlist, $port); } for ($i = 0; $i < @'username; $i++) { ! foreach $hp (&get_port($i)) { ! ($host,$port)=split/:/,$hp; ! $uselist = &'add($uselist, $port); } } foreach $lno (&'array($'listenlist)) { *************** *** 1205,1213 **** } } sub c_accept { local($listenno) = @_; ! local($clientno, $port, $ip, $name, $host, $pass, $regex, $i); $clientno = &'accept($listenno); return unless $clientno; $port = (&'sockname($clientno))[0]; --- 1241,1269 ---- } } + sub parse_plum_client{ + my($str)=@_; + my @a = split/\s+/,$_[0]; + if(@a==3){ + # mask lhost:lport passwd + my @hp = split/:/,$a[1]; + $hp[0] ||= '*'; + $hp[1] ||= $IRCPORT; + splice @a,1,1,@hp[0,1]; + }else{ + # mask:lport passwd + my @hp = split/:/,$a[0]; + $hp[0] ||= '*'; + $hp[1] ||= $IRCPORT; + splice @a,0,1,@hp[0,1],'*'; + } + $a[3] ||= ''; + return @a; # $mask,$listen_host,$listen_addr,$pass + } + sub c_accept { local($listenno) = @_; ! local($clientno, $port, $ip, $name, $pass, $regex, $i,$mask,$listen_port); $clientno = &'accept($listenno); return unless $clientno; $port = (&'sockname($clientno))[0]; *************** *** 1215,1223 **** $name = (&'peername($clientno))[2]; for ($i = 0; $i < @'username; $i++) { foreach $client (&'property($i, 'client')) { ! ($host, $pass) = (split(/\s+/, $client), ''); ! next unless $port == ((split(/\:/, $host))[1] || $IRCPORT); ! $regex = &'regex((split(/\:/, $host))[0]); next unless ($ip =~ /$regex/i || $name =~ /$regex/i); $'clientlist = &'add($'clientlist, $clientno); $'avail[$clientno] = 0; --- 1271,1279 ---- $name = (&'peername($clientno))[2]; for ($i = 0; $i < @'username; $i++) { foreach $client (&'property($i, 'client')) { ! ($mask,undef,$listen_port,$pass)=parse_plum_client($client); ! next unless $port == $listen_port; ! $regex = &'regex($mask); next unless ($ip =~ /$regex/i || $name =~ /$regex/i); $'clientlist = &'add($'clientlist, $clientno); $'avail[$clientno] = 0; *************** *** 1233,1244 **** sub get_port { local($userno) = @_; ! local($host, $pass, $mask, $port, $list); $list = ''; foreach $client (&'property($userno, 'client')) { ! ($host, $pass) = split(/\s+/, $client, 2); ! ($mask, $port) = split(/\:/, $host); ! $list = &'add($list, $port); } return &'array($list); } --- 1289,1299 ---- sub get_port { local($userno) = @_; ! local($list,$listen_host,$listen_port); $list = ''; foreach $client (&'property($userno, 'client')) { ! (undef,$listen_host,$listen_port,undef)=parse_plum_client($client); ! $list = &'add($list,"$listen_host:$listen_port"); } return &'array($list); } *************** *** 1272,1286 **** sub c_init { local($clientno) = @_; ! local($port, $ip, $name, $host, $pass, $regex, $i); $port = (&'sockname($clientno))[0]; $ip = join('.', unpack('C4', pack('N', (&'peername($clientno))[1]))); $name = (&'peername($clientno))[2]; for ($i = 0; $i < @'username; $i++) { foreach $client (&'property($i, 'client')) { ! ($host, $pass) = (split(/\s+/, $client), ''); ! next unless $port == ((split(/\:/, $host))[1] || $IRCPORT); ! $regex = &'regex((split(/\:/, $host))[0]); next unless ($ip =~ /$regex/i || $name =~ /$regex/i); next if ($pass && $pass ne $pass[$clientno]); $'userno[$clientno] = $i; --- 1327,1341 ---- sub c_init { local($clientno) = @_; ! local($port, $ip, $name, $regex, $i,$mask,$listen_port,$pass); $port = (&'sockname($clientno))[0]; $ip = join('.', unpack('C4', pack('N', (&'peername($clientno))[1]))); $name = (&'peername($clientno))[2]; for ($i = 0; $i < @'username; $i++) { foreach $client (&'property($i, 'client')) { ! ($mask,undef,$listen_port,$pass)=parse_plum_client($client); ! next unless $port == $listen_port; ! $regex = &'regex($mask); next unless ($ip =~ /$regex/i || $name =~ /$regex/i); next if ($pass && $pass ne $pass[$clientno]); $'userno[$clientno] = $i;