github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgNet/CurrentIp.go (about)

     1  package kmgNet
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"regexp"
     7  	"strconv"
     8  
     9  	"github.com/bronze1man/kmg/errors"
    10  	"github.com/bronze1man/kmg/kmgCmd"
    11  	"github.com/bronze1man/kmg/kmgPlatform"
    12  )
    13  
    14  // 获取当前地址的列表的字符串
    15  func GetCurrentAddrListString() string {
    16  	addrList, err := net.InterfaceAddrs()
    17  	if err != nil {
    18  		return "[GetCurrentAddrListString] fail " + err.Error()
    19  	}
    20  	out := ""
    21  	for _, addr := range addrList {
    22  		out += addr.String() + ";"
    23  	}
    24  	return out
    25  }
    26  
    27  //一个网络设备上面的地址
    28  type DeviceAddr struct {
    29  	IP        net.IP     //地址上面的ip
    30  	IPNet     *net.IPNet //地址上面的子网
    31  	DevString string     //设备名称 eth0 什么的
    32  }
    33  
    34  // 返回nil表示没找到这个设备,或者这个设备上面没有ip
    35  func MustGetFirstIPByNetDeviceName(devname string) net.IP {
    36  	if !kmgPlatform.IsLinux() {
    37  		panic("[GetFirstIPByNetDeviceName] only support linux now")
    38  	}
    39  	deviceAddrList, err := GetCurrentDeviceAddr()
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  	for _, deviceAddr := range deviceAddrList {
    44  		if deviceAddr.DevString == devname {
    45  			return deviceAddr.IP
    46  		}
    47  	}
    48  	return nil
    49  }
    50  
    51  //目前仅支持linux
    52  func (a DeviceAddr) IpAddrDel() (err error) {
    53  	if !kmgPlatform.IsLinux() {
    54  		panic("[DeviceAddr.IpAddrDel] only support linux now")
    55  	}
    56  	one, _ := a.IPNet.Mask.Size()
    57  	return kmgCmd.CmdString(fmt.Sprintf("ip addr del %s/%d dev %s", a.IP.String(), one, a.DevString)).Run()
    58  }
    59  
    60  //目前仅支持linux
    61  func GetCurrentDeviceAddr() (ipnets []DeviceAddr, err error) {
    62  	if !kmgPlatform.IsLinux() {
    63  		panic("[GetCurrentDeviceAddr] only support linux now")
    64  	}
    65  	out, err := kmgCmd.CmdString("ip addr").RunAndReturnOutput()
    66  	if err != nil {
    67  		return
    68  	}
    69  	return getCurrentDeviceAddrFromIPAddr(out)
    70  }
    71  
    72  //返回当前机器上面的所有ip列表.没有ip会报错
    73  func MustGetCurrentIpList() (ipList []net.IP) {
    74  	if !kmgPlatform.IsLinux() {
    75  		panic("[MustGetCurrentIpList] only support linux now")
    76  	}
    77  	deviceAddrList, err := GetCurrentDeviceAddr()
    78  	if err != nil {
    79  		panic(err)
    80  	}
    81  	if len(deviceAddrList) == 0 {
    82  		panic(errors.New("[MustGetCurrentIpList] do not find any ip address."))
    83  	}
    84  	ipList = make([]net.IP, len(deviceAddrList))
    85  	for i, addr := range deviceAddrList {
    86  		ipList[i] = addr.IP
    87  	}
    88  	return ipList
    89  }
    90  
    91  func MustGetCurrentIpWithPortList(port uint16) (sList []string) {
    92  	if !kmgPlatform.IsLinux() {
    93  		panic("[MustGetCurrentIpWithPortList] only support linux now")
    94  	}
    95  	deviceAddrList, err := GetCurrentDeviceAddr()
    96  	if err != nil {
    97  		panic(err)
    98  	}
    99  	if len(deviceAddrList) == 0 {
   100  		panic(errors.New("[MustGetCurrentIpList] do not find any ip address."))
   101  	}
   102  	sList = make([]string, 0, len(deviceAddrList))
   103  	sPort := strconv.Itoa(int(port))
   104  	for _, addr := range deviceAddrList {
   105  		ones, size := addr.IPNet.Mask.Size()
   106  		if ones == size { // 实践表明 不能监听这种子网只有一个ip的地址.
   107  			continue
   108  		}
   109  		sList = append(sList, net.JoinHostPort(addr.IP.String(), sPort))
   110  	}
   111  	return sList
   112  }
   113  
   114  func getCurrentDeviceAddrFromIPAddr(cmdReturn []byte) (ipnets []DeviceAddr, err error) {
   115  	//可能性1 本地回路     inet 127.0.0.1/8 scope host lo
   116  	//可能性2 物理网卡     inet 10.169.224.99/21 brd 10.169.231.255 scope global eth0
   117  	//可能性3 pptp虚拟网卡 inet 172.20.0.1 peer 172.20.0.2/32 scope global ppp0
   118  	reg := regexp.MustCompile(`inet ([^ ]+).* ([^\s]+)`)
   119  	out := reg.FindAllSubmatch(cmdReturn, -1)
   120  	ipnets = make([]DeviceAddr, len(out))
   121  	for i := range out {
   122  		ip, ipnet, err := net.ParseCIDR(string(out[i][1]))
   123  		if err != nil {
   124  			_, ok := err.(*net.ParseError)
   125  			if !ok {
   126  				return nil, err
   127  			}
   128  			ip, ipnet, err = net.ParseCIDR(string(out[i][1]) + "/32")
   129  			if err != nil {
   130  				return nil, fmt.Errorf("[getCurrentDeviceAddrFromIPAddr] can not parse CIDR or IP [%s]", out[i][0])
   131  			}
   132  		}
   133  		ipnets[i] = DeviceAddr{
   134  			IP:        ip,
   135  			IPNet:     ipnet,
   136  			DevString: string(out[i][2]),
   137  		}
   138  	}
   139  	return
   140  }