@@ -3,6 +3,7 @@ package dns
33import (
44 "context"
55 "crypto/tls"
6+ "errors"
67 "fmt"
78 "io"
89 "net"
@@ -1041,6 +1042,176 @@ func TestServerReuseport(t *testing.T) {
10411042 }
10421043}
10431044
1045+ func TestServerReuseaddr (t * testing.T ) {
1046+ startServerFn := func (t * testing.T , network , addr string , expectSuccess bool ) (* Server , chan error ) {
1047+ t .Helper ()
1048+ wait := make (chan struct {})
1049+ srv := & Server {
1050+ Net : network ,
1051+ Addr : addr ,
1052+ NotifyStartedFunc : func () { close (wait ) },
1053+ ReuseAddr : true ,
1054+ }
1055+
1056+ fin := make (chan error , 1 )
1057+ go func () {
1058+ fin <- srv .ListenAndServe ()
1059+ }()
1060+
1061+ select {
1062+ case <- wait :
1063+ case err := <- fin :
1064+ switch {
1065+ case expectSuccess :
1066+ t .Fatalf ("%s: failed to start server: %v" , t .Name (), err )
1067+ default :
1068+ fin <- err
1069+ return nil , fin
1070+ }
1071+ }
1072+ return srv , fin
1073+ }
1074+
1075+ externalIPFn := func (t * testing.T ) (string , error ) {
1076+ t .Helper ()
1077+ ifaces , err := net .Interfaces ()
1078+ if err != nil {
1079+ return "" , err
1080+ }
1081+ for _ , iface := range ifaces {
1082+ if iface .Flags & net .FlagUp == 0 {
1083+ continue // interface down
1084+ }
1085+ if iface .Flags & net .FlagLoopback != 0 {
1086+ continue // loopback interface
1087+ }
1088+ addrs , err := iface .Addrs ()
1089+ if err != nil {
1090+ return "" , err
1091+ }
1092+ for _ , addr := range addrs {
1093+ var ip net.IP
1094+ switch v := addr .(type ) {
1095+ case * net.IPNet :
1096+ ip = v .IP
1097+ case * net.IPAddr :
1098+ ip = v .IP
1099+ }
1100+ if ip == nil || ip .IsLoopback () {
1101+ continue
1102+ }
1103+ ip = ip .To4 ()
1104+ if ip == nil {
1105+ continue // not an ipv4 address
1106+ }
1107+ return ip .String (), nil
1108+ }
1109+ }
1110+ return "" , errors .New ("are you connected to the network?" )
1111+ }
1112+
1113+ freePortFn := func (t * testing.T ) int {
1114+ t .Helper ()
1115+ addr , err := net .ResolveTCPAddr ("tcp" , "localhost:0" )
1116+ if err != nil {
1117+ t .Fatalf ("unable resolve tcp addr: %s" , err )
1118+ }
1119+
1120+ l , err := net .ListenTCP ("tcp" , addr )
1121+ if err != nil {
1122+ t .Fatalf ("unable listen tcp: %s" , err )
1123+ }
1124+ defer l .Close ()
1125+ return l .Addr ().(* net.TCPAddr ).Port
1126+ }
1127+
1128+ t .Run ("should-fail-tcp" , func (t * testing.T ) {
1129+ // ReuseAddr should fail if you try to bind to exactly the same
1130+ // combination of source address and port.
1131+ // This should fail whether or not ReuseAddr is supported on a
1132+ // particular OS
1133+ ip , err := externalIPFn (t )
1134+ if err != nil {
1135+ t .Skip ("no external IPs found" )
1136+ return
1137+ }
1138+ port := freePortFn (t )
1139+ srv1 , fin1 := startServerFn (t , "tcp" , fmt .Sprintf ("%s:%d" , ip , port ), true )
1140+ srv2 , fin2 := startServerFn (t , "tcp" , fmt .Sprintf ("%s:%d" , ip , port ), false )
1141+ switch {
1142+ case srv2 != nil && srv2 .started :
1143+ t .Fatalf ("second ListenAndServe should not have started" )
1144+ default :
1145+ if err := <- fin2 ; err == nil {
1146+ t .Fatalf ("second ListenAndServe should have returned a startup error: %v" , err )
1147+ }
1148+ }
1149+
1150+ if err := srv1 .Shutdown (); err != nil {
1151+ t .Fatalf ("failed to shutdown first server: %v" , err )
1152+ }
1153+ if err := <- fin1 ; err != nil {
1154+ t .Fatalf ("first ListenAndServe returned error after Shutdown: %v" , err )
1155+ }
1156+ })
1157+ t .Run ("should-succeed-tcp" , func (t * testing.T ) {
1158+ if ! supportsReuseAddr {
1159+ t .Skip ("reuseaddr is not supported" )
1160+ }
1161+ ip , err := externalIPFn (t )
1162+ if err != nil {
1163+ t .Skip ("no external IPs found" )
1164+ return
1165+ }
1166+ port := freePortFn (t )
1167+
1168+ // ReuseAddr should succeed if you try to bind to the same port but a different source address
1169+ srv1 , fin1 := startServerFn (t , "tcp" , fmt .Sprintf ("localhost:%d" , port ), true )
1170+ srv2 , fin2 := startServerFn (t , "tcp" , fmt .Sprintf ("%s:%d" , ip , port ), true )
1171+
1172+ if err := srv1 .Shutdown (); err != nil {
1173+ t .Fatalf ("failed to shutdown first server: %v" , err )
1174+ }
1175+ if err := srv2 .Shutdown (); err != nil {
1176+ t .Fatalf ("failed to shutdown second server: %v" , err )
1177+ }
1178+ if err := <- fin1 ; err != nil {
1179+ t .Fatalf ("first ListenAndServe returned error after Shutdown: %v" , err )
1180+ }
1181+ if err := <- fin2 ; err != nil {
1182+ t .Fatalf ("second ListenAndServe returned error after Shutdown: %v" , err )
1183+ }
1184+ })
1185+ t .Run ("should-succeed-udp" , func (t * testing.T ) {
1186+ if ! supportsReuseAddr {
1187+ t .Skip ("reuseaddr is not supported" )
1188+ }
1189+ ip , err := externalIPFn (t )
1190+ if err != nil {
1191+ t .Skip ("no external IPs found" )
1192+ return
1193+ }
1194+ port := freePortFn (t )
1195+
1196+ // ReuseAddr should succeed if you try to bind to the same port but a different source address
1197+ srv1 , fin1 := startServerFn (t , "udp" , fmt .Sprintf ("localhost:%d" , port ), true )
1198+ srv2 , fin2 := startServerFn (t , "udp" , fmt .Sprintf ("%s:%d" , ip , port ), true )
1199+
1200+ if err := srv1 .Shutdown (); err != nil {
1201+ t .Fatalf ("failed to shutdown first server: %v" , err )
1202+ }
1203+ if err := srv2 .Shutdown (); err != nil {
1204+ t .Fatalf ("failed to shutdown second server: %v" , err )
1205+ }
1206+ if err := <- fin1 ; err != nil {
1207+ t .Fatalf ("first ListenAndServe returned error after Shutdown: %v" , err )
1208+ }
1209+ if err := <- fin2 ; err != nil {
1210+ t .Fatalf ("second ListenAndServe returned error after Shutdown: %v" , err )
1211+ }
1212+ })
1213+ }
1214+
10441215func TestServerRoundtripTsig (t * testing.T ) {
10451216 secret := map [string ]string {"test." : "so6ZGir4GPAqINNh9U5c3A==" }
10461217
0 commit comments