diff --git a/AUTHORS b/AUTHORS index dcd2c205c..9a9eaf6f6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,6 +15,7 @@ Aaron Hopkins Arne Hormann Carlos Nieto Chris Moos +Daniƫl van Eeden DisposaBoy Frederick Mayle Gustavo Kristic diff --git a/driver.go b/driver.go index d310624ad..2b13c1406 100644 --- a/driver.go +++ b/driver.go @@ -20,6 +20,8 @@ import ( "database/sql" "database/sql/driver" "net" + "os" + "strconv" ) // This struct is exported to make the driver directly accessible. @@ -30,6 +32,8 @@ type MySQLDriver struct{} // Custom dial functions must be registered with RegisterDial type DialFunc func(addr string) (net.Conn, error) +var pid string + var dials map[string]DialFunc // RegisterDial registers a custom dial function. It can then be used by the @@ -145,5 +149,6 @@ func (d MySQLDriver) Open(dsn string) (driver.Conn, error) { } func init() { + pid = strconv.Itoa(os.Getpid()) sql.Register("mysql", &MySQLDriver{}) } diff --git a/packets.go b/packets.go index 14395bf9a..fa77b2129 100644 --- a/packets.go +++ b/packets.go @@ -16,6 +16,9 @@ import ( "fmt" "io" "math" + "os" + "path" + "runtime" "time" ) @@ -219,6 +222,7 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { clientTransactions | clientLocalFiles | clientPluginAuth | + clientConnectAttrs | mc.flags&clientLongFlag if mc.cfg.clientFoundRows { @@ -233,7 +237,23 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { // User Password scrambleBuff := scramblePassword(cipher, []byte(mc.cfg.passwd)) + attrs := map[string]string { + "_os": runtime.GOOS, + "_client_name": "Go-MySQL-Driver", + "_pid": pid, + "_platform": runtime.GOARCH, + "program_name": path.Base(os.Args[0]), + } + + attrlen := 0 + for attrname, attrvalue := range attrs { + attrlen += len(attrname) + len(attrvalue) + // one byte to store attrname length and one byte to store attrvalue length + attrlen += 2 + } + pktLen := 4 + 4 + 1 + 23 + len(mc.cfg.user) + 1 + 1 + len(scrambleBuff) + 21 + 1 + pktLen += attrlen + 1 // one byte to store the total length of attrs // To specify a db name if n := len(mc.cfg.dbname); n > 0 { @@ -305,6 +325,19 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { // Assume native client during response pos += copy(data[pos:], "mysql_native_password") data[pos] = 0x00 + pos++ + + // Connection attributes + data[pos] = byte(attrlen) + pos++ + + for attrname, attrvalue := range attrs { + data[pos] = byte(len(attrname)) + pos += 1 + copy(data[pos+1:], attrname) + + data[pos] = byte(len(attrvalue)) + pos += 1 + copy(data[pos+1:], attrvalue) + } // Send Auth packet return mc.writePacket(data)